Add new endpoint to collect all instances 92/141592/2
authoradheli.tavares <adheli.tavares@est.tech>
Mon, 28 Jul 2025 14:01:19 +0000 (15:01 +0100)
committeradheli.tavares <adheli.tavares@est.tech>
Mon, 28 Jul 2025 14:19:15 +0000 (15:19 +0100)
- filter is based on stateResultChange and/or deployState
- can be sorted; default is order by lastMsg/DESC
- can be pageable

Issue-ID: POLICY-5425
Change-Id: Ia98363f5238d6840b3cb70fdc3302a2905962531
Signed-off-by: Eli Tavares <adheli.tavares@est.tech>
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/java/org/onap/policy/clamp/acm/runtime/main/web/AbstractRestController.java
runtime-acm/src/main/resources/openapi/openapi.yaml
runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/contract/InstantiationControllerStubTest.java
runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/rest/InstantiationControllerTest.java

index 9c2a2ac..c8a862c 100644 (file)
@@ -36,6 +36,7 @@ import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement;
 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionRollback;
 import org.onap.policy.clamp.models.acm.concepts.DeployState;
 import org.onap.policy.clamp.models.acm.concepts.LockState;
+import org.onap.policy.clamp.models.acm.concepts.StateChangeResult;
 import org.onap.policy.clamp.models.acm.concepts.SubState;
 import org.onap.policy.clamp.models.acm.persistence.concepts.JpaAutomationComposition;
 import org.onap.policy.clamp.models.acm.persistence.concepts.JpaAutomationCompositionRollback;
@@ -52,6 +53,7 @@ import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.data.domain.Example;
+import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Pageable;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Isolation;
@@ -328,4 +330,32 @@ public class AutomationCompositionProvider {
                     compatibility, dbElementDefinition);
         }
     }
+
+    /**
+     * 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 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(
+            @NonNull final List<StateChangeResult> stateChangeResults,
+            @NonNull final List<DeployState> deployStates,
+            @NonNull final Pageable pageable) {
+        Page<JpaAutomationComposition> page;
+        if (stateChangeResults.isEmpty() && deployStates.isEmpty()) {
+            page = automationCompositionRepository.findAll(pageable);
+        } else if (!stateChangeResults.isEmpty() && deployStates.isEmpty()) {
+            page = automationCompositionRepository.findByStateChangeResultIn(stateChangeResults, pageable);
+        } else if (stateChangeResults.isEmpty()) {
+            page = automationCompositionRepository.findByDeployStateIn(deployStates, pageable);
+        } else {
+            page = automationCompositionRepository.findByStateChangeResultInAndDeployStateIn(
+                stateChangeResults, deployStates, pageable);
+        }
+
+        return ProviderUtils.asEntityList(page.toList());
+    }
 }
index 7a1c61f..10fe0b1 100644 (file)
@@ -1,6 +1,6 @@
 /*-
  * ============LICENSE_START=======================================================
- *  Copyright (C) 2021-2022,2024 Nordix Foundation.
+ *  Copyright (C) 2021-2022,2024-2025 OpenInfra Foundation Europe. 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.
@@ -24,8 +24,11 @@ import java.util.Collection;
 import java.util.List;
 import org.onap.policy.clamp.models.acm.concepts.DeployState;
 import org.onap.policy.clamp.models.acm.concepts.LockState;
+import org.onap.policy.clamp.models.acm.concepts.StateChangeResult;
 import org.onap.policy.clamp.models.acm.concepts.SubState;
 import org.onap.policy.clamp.models.acm.persistence.concepts.JpaAutomationComposition;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.stereotype.Repository;
 
@@ -36,7 +39,17 @@ public interface AutomationCompositionRepository extends JpaRepository<JpaAutoma
 
     List<JpaAutomationComposition> findByDeployStateIn(Collection<DeployState> deployStates);
 
+    Page<JpaAutomationComposition> findByDeployStateIn(Collection<DeployState> deployStates,
+                                                       Pageable pageable);
+
     List<JpaAutomationComposition> findByLockStateIn(Collection<LockState> lockStates);
 
     List<JpaAutomationComposition> findBySubStateIn(Collection<SubState> subStates);
+
+    Page<JpaAutomationComposition> findByStateChangeResultInAndDeployStateIn(
+            Collection<StateChangeResult> stateChangeResults, Collection<DeployState> deployStates,
+            Pageable pageable);
+
+    Page<JpaAutomationComposition> findByStateChangeResultIn(Collection<StateChangeResult> stateChangeResults,
+                                                             Pageable pageable);
 }
index caf4f31..c9df95d 100644 (file)
@@ -27,6 +27,7 @@ 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.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyCollection;
 import static org.mockito.ArgumentMatchers.anyIterable;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.mock;
@@ -44,6 +45,7 @@ import org.onap.policy.clamp.models.acm.concepts.AutomationComposition;
 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositions;
 import org.onap.policy.clamp.models.acm.concepts.DeployState;
 import org.onap.policy.clamp.models.acm.concepts.LockState;
+import org.onap.policy.clamp.models.acm.concepts.StateChangeResult;
 import org.onap.policy.clamp.models.acm.persistence.concepts.JpaAutomationComposition;
 import org.onap.policy.clamp.models.acm.persistence.concepts.JpaAutomationCompositionElement;
 import org.onap.policy.clamp.models.acm.persistence.concepts.JpaAutomationCompositionRollback;
@@ -56,6 +58,7 @@ import org.onap.policy.common.utils.resources.ResourceUtils;
 import org.onap.policy.models.base.PfConceptKey;
 import org.onap.policy.models.base.PfModelRuntimeException;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
+import org.springframework.data.domain.Page;
 import org.springframework.data.domain.PageImpl;
 import org.springframework.data.domain.PageRequest;
 import org.springframework.data.domain.Pageable;
@@ -412,4 +415,54 @@ class AutomationCompositionProviderTest {
                 .validateInstanceEndpoint(wrongCompositionId, automationComposition))
                 .hasMessageContaining("do not match with");
     }
+
+    @Test
+    void testGetAcInstancesByFilter() {
+        Page<JpaAutomationComposition> mockPage = new PageImpl<>(inputAutomationCompositionsJpa);
+        var acRepository = mock(AutomationCompositionRepository.class);
+        when(acRepository.findByStateChangeResultIn(anyCollection(), any(Pageable.class)))
+            .thenReturn(mockPage);
+        when(acRepository.findByDeployStateIn(anyCollection(), any(Pageable.class)))
+            .thenReturn(mockPage);
+
+        var stateChangeResults = new ArrayList<StateChangeResult>();
+        var deployStates = new ArrayList<DeployState>();
+        var pageable = Pageable.unpaged();
+        when(acRepository.findByStateChangeResultInAndDeployStateIn(
+            stateChangeResults, deployStates, pageable)).thenReturn(mockPage);
+        when(acRepository.findAll(any(Pageable.class))).thenReturn(mockPage);
+        var acProvider = new AutomationCompositionProvider(acRepository,
+            mock(AutomationCompositionElementRepository.class), mock(AutomationCompositionRollbackRepository.class));
+
+        var acInstances = acProvider.getAcInstancesByStateResultDeployState(stateChangeResults, deployStates, pageable);
+        assertNotNull(acInstances);
+        assertEquals(2, acInstances.size());
+
+        stateChangeResults.add(StateChangeResult.NO_ERROR);
+        acInstances = acProvider.getAcInstancesByStateResultDeployState(stateChangeResults, deployStates, pageable);
+        assertNotNull(acInstances);
+
+        deployStates.add(DeployState.DEPLOYED);
+        acInstances = acProvider.getAcInstancesByStateResultDeployState(stateChangeResults, deployStates, pageable);
+        assertNotNull(acInstances);
+
+        stateChangeResults.clear();
+        acInstances = acProvider.getAcInstancesByStateResultDeployState(stateChangeResults, deployStates, pageable);
+        assertNotNull(acInstances);
+    }
+
+    @Test
+    void testGetAcInstancesByFilterWithNull() {
+        var provider = new AutomationCompositionProvider(mock(AutomationCompositionRepository.class),
+            mock(AutomationCompositionElementRepository.class), mock(AutomationCompositionRollbackRepository.class));
+        var stateChangeResults = new ArrayList<StateChangeResult>();
+        var deployStates = new ArrayList<DeployState>();
+        var pageable = Pageable.unpaged();
+        assertThrows(NullPointerException.class, () ->
+            provider.getAcInstancesByStateResultDeployState(null, deployStates, pageable));
+        assertThrows(NullPointerException.class, () ->
+            provider.getAcInstancesByStateResultDeployState(stateChangeResults, null, pageable));
+        assertThrows(NullPointerException.class, () ->
+            provider.getAcInstancesByStateResultDeployState(stateChangeResults, deployStates, null));
+    }
 }
index 4e9ca3d..9a79549 100644 (file)
@@ -23,6 +23,8 @@ package org.onap.policy.clamp.acm.runtime.instantiation;
 
 import jakarta.validation.Valid;
 import jakarta.ws.rs.core.Response.Status;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.UUID;
 import java.util.stream.Collectors;
@@ -49,12 +51,14 @@ import org.onap.policy.clamp.models.acm.persistence.provider.AcDefinitionProvide
 import org.onap.policy.clamp.models.acm.persistence.provider.AcInstanceStateResolver;
 import org.onap.policy.clamp.models.acm.persistence.provider.AutomationCompositionProvider;
 import org.onap.policy.clamp.models.acm.persistence.provider.ParticipantProvider;
+import org.onap.policy.clamp.models.acm.persistence.provider.ProviderUtils;
 import org.onap.policy.clamp.models.acm.utils.AcmUtils;
 import org.onap.policy.common.parameters.BeanValidationResult;
 import org.onap.policy.models.base.PfModelRuntimeException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -496,4 +500,34 @@ public class AutomationCompositionInstantiationProvider {
         participantProvider.checkRegisteredParticipant(acDefinition);
         return acDefinition;
     }
+
+    /**
+     * 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 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,
+        final Pageable pageable) {
+
+        List<StateChangeResult> stateChangeResultList = new ArrayList<>();
+        if (stateChangeResults != null) {
+            Arrays.stream(stateChangeResults.split(","))
+                .forEach(stateChangeResult -> stateChangeResultList.add(StateChangeResult.valueOf(stateChangeResult)));
+        }
+
+        List<DeployState> deployStateList = new ArrayList<>();
+        if (deployStates != null) {
+            Arrays.stream(deployStates.split(","))
+                .forEach(deployState -> deployStateList.add(DeployState.valueOf(deployState)));
+        }
+
+        var instances = automationCompositionProvider.getAcInstancesByStateResultDeployState(stateChangeResultList,
+            deployStateList, pageable);
+        return new AutomationCompositions(instances);
+    }
 }
index 494d3d5..5fc5f2c 100644 (file)
@@ -98,6 +98,26 @@ public class InstantiationController extends AbstractRestController implements A
         return ResponseEntity.ok().body(provider.getAutomationCompositions(compositionId, name, version, pageable));
     }
 
+    /**
+     * Queries automation composition instances based on deployment state and state change results.
+     *
+     * @param deployStates the deployment states to filter automation compositions
+     * @param stateChangeResults the state change results to filter automation compositions
+     * @param page the page number for pagination; may be null
+     * @param size the size of the page for pagination; may be null
+     * @param sort the field to sort by; may be null
+     * @param sortOrder the sorting order (ASC or DESC); may be null
+     * @param requestId request ID used in ONAP logging
+     * @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) {
+        var pageable = getPageableWithSorting(page, size, sort, sortOrder);
+        var instances = provider.getAcInstancesByStateResultDeployState(stateChangeResults, deployStates, pageable);
+        return ResponseEntity.ok().body(instances);
+    }
+
     /**
      * Deletes an automation composition.
      *
index ab54dff..269c86c 100644 (file)
@@ -95,4 +95,10 @@ public class InstantiationControllerStub extends AbstractRestController implemen
     public ResponseEntity<Void> rollbackCompositionInstance(UUID compositionId, UUID instanceId) {
         return new ResponseEntity<>(HttpStatus.ACCEPTED);
     }
+
+    @Override
+    public ResponseEntity<AutomationCompositions> queryCompositionInstancesByStateChangeDeployState(String deployState,
+            String stateChangeResult, Integer page, Integer size, String sort, String sortOrder, UUID onapRequestId) {
+        return stubUtils.getResponse(pathToAllInstances, AutomationCompositions.class);
+    }
 }
index 636f486..5f040ce 100644 (file)
@@ -24,9 +24,11 @@ import jakarta.ws.rs.core.MediaType;
 import jakarta.ws.rs.core.Response;
 import java.net.URI;
 import java.net.URISyntaxException;
+import org.apache.commons.lang3.StringUtils;
 import org.onap.policy.clamp.common.acm.exception.AutomationCompositionRuntimeException;
 import org.springframework.data.domain.PageRequest;
 import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
 import org.springframework.web.bind.annotation.RequestMapping;
 
 /**
@@ -54,4 +56,32 @@ public abstract class AbstractRestController {
     protected Pageable getPageable(Integer page, Integer size) {
         return page != null && size != null ? PageRequest.of(page, size) : Pageable.unpaged();
     }
+
+    /**
+     * Retrieves a {@link Pageable} object with sorting capabilities based on the given page, size, sort field,
+     * and sort direction.
+     * If the sort field is not provided or is blank, it defaults to "lastMsg".
+     * If the sort direction is not provided or is blank, it defaults to "DESC".
+     * If either the page or size is null, an unpaged {@link Pageable} is returned.
+     *
+     * @param page the page number to be retrieved (zero-based indexing); if null, the result will be unpaged
+     * @param size the size of the page to be retrieved; if null, the result will be unpaged
+     * @param sort the field by which to sort; defaults to "lastMsg" if blank
+     * @param sortOrder the direction of sorting, either "ASC" or "DESC"; defaults to "DESC" if blank
+     * @return a {@link Pageable} object with the specified paging and sorting parameters,
+     *      or unpaged if page or size is null
+     */
+    protected Pageable getPageableWithSorting(Integer page, Integer size, String sort, String sortOrder) {
+        if (StringUtils.isBlank(sort)) {
+            sort = "lastMsg";
+        }
+
+        if (StringUtils.isBlank(sortOrder)) {
+            sortOrder = "DESC";
+        }
+
+        var sorting = Sort.by(Sort.Direction.fromString(sortOrder), sort);
+
+        return page != null && size != null ? PageRequest.of(page, size).withSort(sorting) : Pageable.unpaged();
+    }
 }
index 68e43e6..6bc692e 100644 (file)
@@ -1734,6 +1734,134 @@ paths:
             api-version: 8.2.1
             last-mod-release: Paris
           x-codegen-request-body-name: body
+  /instances:
+    get:
+      tags:
+        - 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
+      parameters:
+        - name: deployState
+          in: query
+          required: false
+          schema:
+            type: string
+          description: Filter to get instances by deployState (two or more to be comma-separated)
+        - name: stateChangeResult
+          in: query
+          required: false
+          schema:
+            type: string
+          description: Filter to get instances by stateChangeResult (two or more to be comma-separated)
+        - name: page
+          in: query
+          required: false
+          description: Zero-based page number, must not be negative.
+          schema:
+            type: integer
+        - name: size
+          in: query
+          required: false
+          description: The size of the page to be returned, must be greater than 0.
+          schema:
+            type: integer
+        - name: sort
+          in: query
+          required: false
+          description: Sort the list by a property
+          schema:
+            type: string
+        - name: sortOrder
+          in: query
+          required: false
+          description: Order to sort the list - ASC or DESC
+          schema:
+            type: string
+        - name: X-onap-RequestId
+          in: header
+          description: RequestID for http transaction
+          schema:
+            type: string
+            format: uuid
+      responses:
+        200:
+          description: Serialised instance of
+            [AutomationCompositions](https://github.com/onap/policy-clamp/blob/master/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/AutomationCompositions.java)
+            containing a list of automation composition instances found
+          headers:
+            X-LatestVersion:
+              $ref: '#/components/headers/X-LatestVersion'
+            X-PatchVersion:
+              $ref: '#/components/headers/X-PatchVersion'
+            X-MinorVersion:
+              $ref: '#/components/headers/X-MinorVersion'
+            X-onap-RequestId:
+              $ref: '#/components/headers/X-onap-RequestId'
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/AutomationCompositions'
+              example:
+                externalValue: 'https://raw.githubusercontent.com/onap/policy-clamp/master/runtime-acm/src/main/resources/openapi/examples/getAllCompositionInstancesResponse.json'
+            application/yaml:
+              schema:
+                $ref: '#/components/schemas/AutomationCompositions'
+              example:
+                externalValue: 'https://raw.githubusercontent.com/onap/policy-clamp/master/runtime-acm/src/main/resources/openapi/examples/getAllCompositionInstancesResponse.yaml'
+        401:
+          description: Authentication Error, returns an instance of
+            [SimpleResponse](https://github.com/onap/policy-clamp/blob/master/models/src/main/java/org/onap/policy/clamp/models/acm/messages/rest/SimpleResponse.java)
+          headers:
+            X-LatestVersion:
+              $ref: '#/components/headers/X-LatestVersion'
+            X-PatchVersion:
+              $ref: '#/components/headers/X-PatchVersion'
+            X-MinorVersion:
+              $ref: '#/components/headers/X-MinorVersion'
+            X-onap-RequestId:
+              $ref: '#/components/headers/X-onap-RequestId'
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/SimpleResponse'
+        404:
+          description: The specified automation composition definition was not found, returns an instance of
+            [SimpleResponse](https://github.com/onap/policy-clamp/blob/master/models/src/main/java/org/onap/policy/clamp/models/acm/messages/rest/SimpleResponse.java)
+          headers:
+            X-LatestVersion:
+              $ref: '#/components/headers/X-LatestVersion'
+            X-PatchVersion:
+              $ref: '#/components/headers/X-PatchVersion'
+            X-MinorVersion:
+              $ref: '#/components/headers/X-MinorVersion'
+            X-onap-RequestId:
+              $ref: '#/components/headers/X-onap-RequestId'
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/SimpleResponse'
+        500:
+          description: Internal Server Error, returns an instance of
+            [SimpleResponse](https://github.com/onap/policy-clamp/blob/master/models/src/main/java/org/onap/policy/clamp/models/acm/messages/rest/SimpleResponse.java)
+          headers:
+            X-LatestVersion:
+              $ref: '#/components/headers/X-LatestVersion'
+            X-PatchVersion:
+              $ref: '#/components/headers/X-PatchVersion'
+            X-MinorVersion:
+              $ref: '#/components/headers/X-MinorVersion'
+            X-onap-RequestId:
+              $ref: '#/components/headers/X-onap-RequestId'
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/SimpleResponse'
+      security:
+        - basicAuth: []
+      x-interface info:
+        api-version: 8.2.1
+        last-mod-release: Paris
 components:
   securitySchemes:
     basicAuth:
index d270d6c..cafaf05 100644 (file)
@@ -60,8 +60,8 @@ class InstantiationControllerStubTest extends CommonRestController {
         var invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT
                 + "/" + COMPOSITION_ID
                 + "/" + INSTANTIATION_ENDPOINT);
-        var respPost = invocationBuilder.get();
-        assertThat(Response.Status.OK.getStatusCode()).isEqualTo(respPost.getStatus());
+        var response = invocationBuilder.get();
+        assertThat(Response.Status.OK.getStatusCode()).isEqualTo(response.getStatus());
     }
 
     @Test
@@ -70,8 +70,8 @@ class InstantiationControllerStubTest extends CommonRestController {
                 + "/" + COMPOSITION_ID
                 + "/" + INSTANTIATION_ENDPOINT
                 + "/" + INSTANCE_ID);
-        var respPost = invocationBuilder.get();
-        assertThat(Response.Status.OK.getStatusCode()).isEqualTo(respPost.getStatus());
+        var response = invocationBuilder.get();
+        assertThat(Response.Status.OK.getStatusCode()).isEqualTo(response.getStatus());
     }
 
     @Test
@@ -80,8 +80,9 @@ class InstantiationControllerStubTest extends CommonRestController {
                 + "/" + COMPOSITION_ID
                 + "/" + INSTANTIATION_ENDPOINT
                 + "/" + INSTANCE_ID);
-        var respPost = invocationBuilder.put(Entity.json(new AcInstanceStateUpdate()));
-        assertThat(Response.Status.ACCEPTED.getStatusCode()).isEqualTo(respPost.getStatus());
+        var put = invocationBuilder.put(Entity.json(new AcInstanceStateUpdate()));
+        assertThat(Response.Status.ACCEPTED.getStatusCode()).isEqualTo(put.getStatus());
+        put.close();
     }
 
     @Test
@@ -91,6 +92,7 @@ class InstantiationControllerStubTest extends CommonRestController {
                 + "/" + INSTANTIATION_ENDPOINT);
         var respPost = invocationBuilder.post(Entity.json(new AutomationComposition()));
         assertThat(Response.Status.OK.getStatusCode()).isEqualTo(respPost.getStatus());
+        respPost.close();
     }
 
     @Test
@@ -99,8 +101,9 @@ class InstantiationControllerStubTest extends CommonRestController {
                 + "/" + COMPOSITION_ID
                 + "/" + INSTANTIATION_ENDPOINT
                 + "/" + INSTANCE_ID);
-        var respPost = invocationBuilder.delete();
-        assertThat(Response.Status.OK.getStatusCode()).isEqualTo(respPost.getStatus());
+        var delete = invocationBuilder.delete();
+        assertThat(Response.Status.OK.getStatusCode()).isEqualTo(delete.getStatus());
+        delete.close();
     }
 
     @Test
@@ -112,5 +115,13 @@ class InstantiationControllerStubTest extends CommonRestController {
             + "/" + ROLLBACK);
         var respPost = invocationBuilder.post(Entity.json(new AcInstanceStateUpdate()));
         assertThat(Response.Status.ACCEPTED.getStatusCode()).isEqualTo(respPost.getStatus());
+        respPost.close();
+    }
+
+    @Test
+    void testGetInstances() {
+        var invocationBuilder = super.sendRequest(INSTANTIATION_ENDPOINT);
+        var response = invocationBuilder.get();
+        assertThat(Response.Status.OK.getStatusCode()).isEqualTo(response.getStatus());
     }
 }
index d214e73..33703ee 100644 (file)
@@ -56,6 +56,7 @@ import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
 import org.springframework.boot.test.web.server.LocalServerPort;
 import org.springframework.data.domain.Pageable;
+import org.springframework.test.annotation.DirtiesContext;
 import org.springframework.test.context.ActiveProfiles;
 import org.springframework.test.context.junit.jupiter.SpringExtension;
 
@@ -66,9 +67,10 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
 @ExtendWith(SpringExtension.class)
 @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
 @ActiveProfiles({ "test", "default" })
+@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
 class InstantiationControllerTest extends CommonRestController {
 
-    private static final int NUMBER_ISTANCES = 10;
+    private static final int NUMBER_INSTANCES = 10;
     private static final String AC_INSTANTIATION_CREATE_JSON = "src/test/resources/rest/acm/AutomationComposition.json";
     private static final String AC_VERSIONING_YAML = "src/test/resources/rest/acm/AutomationCompositionVersioning.yaml";
 
@@ -147,6 +149,7 @@ class InstantiationControllerTest extends CommonRestController {
         var compositionId = createAcDefinitionInDB("Create");
         var automationCompositionFromRsc =
                 InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Create");
+        assertNotNull(automationCompositionFromRsc);
         automationCompositionFromRsc.setCompositionId(compositionId);
 
         var instResponse = createAutomationComposition(compositionId, automationCompositionFromRsc,
@@ -178,6 +181,7 @@ class InstantiationControllerTest extends CommonRestController {
         var compositionId = createAcDefinitionInDB("CreateBadRequest");
         var automationCompositionFromRsc = InstantiationUtils
                 .getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "CreateBadRequest");
+        assertNotNull(automationCompositionFromRsc);
         automationCompositionFromRsc.setCompositionId(compositionId);
 
         createAutomationComposition(compositionId, automationCompositionFromRsc, Response.Status.CREATED);
@@ -195,6 +199,7 @@ class InstantiationControllerTest extends CommonRestController {
         var compositionId = createAcDefinitionInDB(serviceTemplateVer);
         var automationCompositionFromRsc = InstantiationUtils
             .getAutomationCompositionFromYaml(AC_VERSIONING_YAML, "Versioning");
+        assertNotNull(automationCompositionFromRsc);
         automationCompositionFromRsc.setCompositionId(compositionId);
         var instResponse =
             createAutomationComposition(compositionId, automationCompositionFromRsc, Response.Status.CREATED);
@@ -217,6 +222,7 @@ class InstantiationControllerTest extends CommonRestController {
         var compositionId = createAcDefinitionInDB("Query");
         var automationComposition =
                 InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Query");
+        assertNotNull(automationComposition);
         automationComposition.setCompositionId(compositionId);
 
         instantiationProvider.createAutomationComposition(compositionId, automationComposition);
@@ -239,8 +245,9 @@ class InstantiationControllerTest extends CommonRestController {
         var compositionId = createAcDefinitionInDB("Query");
         var automationComposition =
             InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Query");
+        assertNotNull(automationComposition);
         automationComposition.setCompositionId(compositionId);
-        for (var i = 0; i < NUMBER_ISTANCES; i++) {
+        for (var i = 0; i < NUMBER_INSTANCES; i++) {
             automationComposition.setName("acm_" + i);
             instantiationProvider.createAutomationComposition(compositionId, automationComposition);
         }
@@ -260,7 +267,7 @@ class InstantiationControllerTest extends CommonRestController {
             assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
             var resultList = response.readEntity(AutomationCompositions.class);
             assertNotNull(resultList);
-            assertThat(resultList.getAutomationCompositionList()).hasSizeGreaterThanOrEqualTo(NUMBER_ISTANCES);
+            assertThat(resultList.getAutomationCompositionList()).hasSizeGreaterThanOrEqualTo(NUMBER_INSTANCES);
         }
     }
 
@@ -279,6 +286,7 @@ class InstantiationControllerTest extends CommonRestController {
         var compositionId = createAcDefinitionInDB("Get");
         var automationComposition =
                 InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Get");
+        assertNotNull(automationComposition);
         automationComposition.setCompositionId(compositionId);
 
         instantiationProvider.createAutomationComposition(compositionId, automationComposition);
@@ -299,12 +307,14 @@ class InstantiationControllerTest extends CommonRestController {
         var compositionId = createAcDefinitionInDB("Update");
         var automationCompositionCreate =
                 InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Update");
+        assertNotNull(automationCompositionCreate);
         automationCompositionCreate.setCompositionId(compositionId);
 
         var response = instantiationProvider.createAutomationComposition(compositionId, automationCompositionCreate);
 
         var automationComposition =
                 InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_UPDATE_JSON, "Update");
+        assertNotNull(automationComposition);
         automationComposition.setCompositionId(compositionId);
         automationComposition.setInstanceId(response.getInstanceId());
         automationComposition.getElements().values()
@@ -334,6 +344,7 @@ class InstantiationControllerTest extends CommonRestController {
         var compositionId = createAcDefinitionInDB("Delete");
         var automationCompositionFromRsc =
                 InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Delete");
+        assertNotNull(automationCompositionFromRsc);
         automationCompositionFromRsc.setCompositionId(compositionId);
 
         var instResponse =
@@ -358,6 +369,7 @@ class InstantiationControllerTest extends CommonRestController {
         var compositionId = createAcDefinitionInDB("DeleteNotFound");
         var automationCompositionFromRsc =
                 InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "DelNotFound");
+        assertNotNull(automationCompositionFromRsc);
         automationCompositionFromRsc.setCompositionId(compositionId);
 
         instantiationProvider.createAutomationComposition(compositionId, automationCompositionFromRsc);
@@ -382,10 +394,11 @@ class InstantiationControllerTest extends CommonRestController {
         // instance not valid state
         var automationCompositionFromRsc =
                 InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "NotValid");
+        assertNotNull(automationCompositionFromRsc);
         automationCompositionFromRsc.setCompositionId(compositionId);
-        var instanceResponce =
+        var instanceResponse =
                 instantiationProvider.createAutomationComposition(compositionId, automationCompositionFromRsc);
-        url = getInstanceEndPoint(compositionId, instanceResponce.getInstanceId()) + "/rollback";
+        url = getInstanceEndPoint(compositionId, instanceResponse.getInstanceId()) + "/rollback";
         invocationBuilder = super.sendRequest(url);
         try (var resp = invocationBuilder.post(Entity.entity("", MediaType.APPLICATION_JSON))) {
             assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), resp.getStatus());
@@ -406,6 +419,7 @@ class InstantiationControllerTest extends CommonRestController {
         var compositionId = createAcDefinitionInDB("Deploy_BadRequest");
         var acFromRsc =
                 InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "BadRequest");
+        assertNotNull(acFromRsc);
         acFromRsc.setCompositionId(compositionId);
 
         var instResponse = instantiationProvider.createAutomationComposition(compositionId, acFromRsc);
@@ -425,6 +439,7 @@ class InstantiationControllerTest extends CommonRestController {
         var compositionId = createAcDefinitionInDB("Deploy");
         var automationComposition =
                 InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Command");
+        assertNotNull(automationComposition);
         automationComposition.setCompositionId(compositionId);
         var instResponse = instantiationProvider.createAutomationComposition(compositionId, automationComposition);
 
@@ -438,6 +453,28 @@ class InstantiationControllerTest extends CommonRestController {
         }
     }
 
+    @Test
+    void test_QueryCompositionInstancesByStateChangeDeployState() {
+        // 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", 10);
+        validateQueryPageable("instances?page=1&size=4", 4);
+        validateQueryPageable("instances?size=4", 10); // only works if page is also informed, so listAll
+        validateQueryPageable("instances?stateChangeResult=FAILED,TIMEOUT", 0);
+        validateQueryPageable("instances?deployState=UNDEPLOYED", 10);
+        validateQueryPageable("instances?stateChangeResult=NO_ERROR&deployState=UNDEPLOYED", 0);
+        validateQueryPageable("instances?sort=name&sortOrder=DESC", 10);
+    }
+
     private UUID createAcDefinitionInDB(String name) {
         var serviceTemplateCreate = new ToscaServiceTemplate(serviceTemplate);
         serviceTemplateCreate.setName(name);