From: lukegleeson Date: Thu, 2 Jun 2022 09:56:43 +0000 (+0100) Subject: Get cm-handle state endpoint X-Git-Tag: 3.1.0~90 X-Git-Url: https://gerrit.onap.org/r/gitweb?p=cps.git;a=commitdiff_plain;h=78062a1c3f4e303714103dfcb7d9552a0b081eb0 Get cm-handle state endpoint Added new get cm-handle state endpoint Refactored RestOutputCmHandleState to CmHandleCompositeState Created new RestOutputCmHandleCompositeState OpenApi object ^This is done so that we get '"state: {" at the start of JSON response Refactored RestOutputCmHandleStateMapper to CmHandleStateMapper Added more detailed composite state to get cmHandleDetails endpoint tests Rebased code Code rebased on top of 129658: Unable to change state from LOCKED to ADVISED | https://gerrit.onap.org/r/c/cps/+/129658 which fixes output error Issue-ID: CPS-1019 Signed-off-by: mpriyank Signed-off-by: lukegleeson Change-Id: I361117c98c256a4aa578c13d21926bc6d7876a15 --- diff --git a/cps-ncmp-rest/docs/openapi/components.yaml b/cps-ncmp-rest/docs/openapi/components.yaml index 248b1daa6..cf254e511 100644 --- a/cps-ncmp-rest/docs/openapi/components.yaml +++ b/cps-ncmp-rest/docs/openapi/components.yaml @@ -209,7 +209,7 @@ components: publicCmHandleProperties: $ref: '#/components/schemas/CmHandlePublicProperties' state: - $ref: '#/components/schemas/RestOutputCmHandleState' + $ref: '#/components/schemas/CmHandleCompositeState' CmHandlePublicProperties: type: array items: @@ -217,7 +217,7 @@ components: additionalProperties: type: string example: Book Type - RestOutputCmHandleState: + CmHandleCompositeState: type: object properties: cmHandleState: @@ -268,6 +268,12 @@ components: publicCmHandleProperties: $ref: '#/components/schemas/CmHandlePublicProperties' + RestOutputCmHandleCompositeState: + type: object + properties: + state: + $ref: '#/components/schemas/CmHandleCompositeState' + examples: dataSampleRequest: summary: Sample request diff --git a/cps-ncmp-rest/docs/openapi/ncmp.yml b/cps-ncmp-rest/docs/openapi/ncmp.yml index 3259032f2..8bdaa82d8 100755 --- a/cps-ncmp-rest/docs/openapi/ncmp.yml +++ b/cps-ncmp-rest/docs/openapi/ncmp.yml @@ -293,6 +293,10 @@ retrieveCmHandleDetailsById: application/json: schema: $ref: 'components.yaml#/components/schemas/RestOutputCmHandle' + 400: + $ref: 'components.yaml#/components/responses/BadRequest' + 401: + $ref: 'components.yaml#/components/responses/Unauthorized' 404: $ref: 'components.yaml#/components/responses/NotFound' 500: @@ -314,6 +318,35 @@ getCmHandlePropertiesById: application/json: schema: $ref: 'components.yaml#/components/schemas/RestOutputCmHandlePublicProperties' + 400: + $ref: 'components.yaml#/components/responses/BadRequest' + 401: + $ref: 'components.yaml#/components/responses/Unauthorized' + 404: + $ref: 'components.yaml#/components/responses/NotFound' + 500: + $ref: 'components.yaml#/components/responses/InternalServerError' + +getCmHandleStateById: + get: + description: Get CM handle state by cm handle id + tags: + - network-cm-proxy + summary: Get CM handle state + operationId: getCmHandleStateByCmHandleId + parameters: + - $ref: 'components.yaml#/components/parameters/cmHandleInPath' + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: 'components.yaml#/components/schemas/RestOutputCmHandleCompositeState' + 400: + $ref: 'components.yaml#/components/responses/BadRequest' + 401: + $ref: 'components.yaml#/components/responses/Unauthorized' 404: $ref: 'components.yaml#/components/responses/NotFound' 500: diff --git a/cps-ncmp-rest/docs/openapi/openapi.yml b/cps-ncmp-rest/docs/openapi/openapi.yml index 81ebf05ed..ad7dd1d4f 100755 --- a/cps-ncmp-rest/docs/openapi/openapi.yml +++ b/cps-ncmp-rest/docs/openapi/openapi.yml @@ -46,3 +46,6 @@ paths: /v1/ch/id-searches: $ref: 'ncmp.yml#/searchCmHandleIds' + + /v1/ch/{cm-handle}/state: + $ref: 'ncmp.yml#/getCmHandleStateById' diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java index fb234ef71..7abefe679 100755 --- a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java +++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java @@ -40,15 +40,17 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.onap.cps.ncmp.api.NetworkCmProxyDataService; import org.onap.cps.ncmp.api.impl.exception.InvalidTopicException; +import org.onap.cps.ncmp.api.inventory.CompositeState; import org.onap.cps.ncmp.api.models.CmHandleQueryApiParameters; import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; import org.onap.cps.ncmp.rest.api.NetworkCmProxyApi; import org.onap.cps.ncmp.rest.executor.CpsNcmpTaskExecutor; -import org.onap.cps.ncmp.rest.mapper.RestOutputCmHandleStateMapper; +import org.onap.cps.ncmp.rest.mapper.CmHandleStateMapper; import org.onap.cps.ncmp.rest.model.CmHandlePublicProperties; import org.onap.cps.ncmp.rest.model.CmHandleQueryParameters; import org.onap.cps.ncmp.rest.model.RestModuleReference; import org.onap.cps.ncmp.rest.model.RestOutputCmHandle; +import org.onap.cps.ncmp.rest.model.RestOutputCmHandleCompositeState; import org.onap.cps.ncmp.rest.model.RestOutputCmHandlePublicProperties; import org.onap.cps.ncmp.rest.util.DeprecationHelper; import org.onap.cps.utils.CpsValidator; @@ -73,7 +75,7 @@ public class NetworkCmProxyController implements NetworkCmProxyApi { private final DeprecationHelper deprecationHelper; private final NcmpRestInputMapper ncmpRestInputMapper; - private final RestOutputCmHandleStateMapper restOutputCmHandleStateMapper; + private final CmHandleStateMapper cmHandleStateMapper; private final CpsNcmpTaskExecutor cpsNcmpTaskExecutor; @Value("${notification.async.executor.time-out-value-in-ms:2000}") @@ -253,7 +255,7 @@ public class NetworkCmProxyController implements NetworkCmProxyApi { /** * Get Cm Handle Properties by Cm Handle Id. * @param cmHandleId cm-handle identifier - * @return cm handle and its properties + * @return cm handle properties */ @Override public ResponseEntity getCmHandlePublicPropertiesByCmHandleId( @@ -266,6 +268,21 @@ public class NetworkCmProxyController implements NetworkCmProxyApi { return ResponseEntity.ok(restOutputCmHandlePublicProperties); } + /** + * Get Cm Handle State by Cm Handle Id. + * @param cmHandleId cm-handle identifier + * @return cm handle state + */ + @Override + public ResponseEntity getCmHandleStateByCmHandleId( + final String cmHandleId) { + final CompositeState cmHandleState = networkCmProxyDataService.getCmHandleCompositeState(cmHandleId); + final RestOutputCmHandleCompositeState restOutputCmHandleCompositeState = + new RestOutputCmHandleCompositeState(); + restOutputCmHandleCompositeState.setState(cmHandleStateMapper.toCmHandleCompositeState(cmHandleState)); + return ResponseEntity.ok(restOutputCmHandleCompositeState); + } + /** * Return module references for a cm handle. * @@ -286,7 +303,7 @@ public class NetworkCmProxyController implements NetworkCmProxyApi { restOutputCmHandle.setCmHandle(ncmpServiceCmHandle.getCmHandleId()); cmHandlePublicProperties.add(ncmpServiceCmHandle.getPublicProperties()); restOutputCmHandle.setPublicCmHandleProperties(cmHandlePublicProperties); - restOutputCmHandle.setState(restOutputCmHandleStateMapper.toRestOutputCmHandleState( + restOutputCmHandle.setState(cmHandleStateMapper.toCmHandleCompositeState( ncmpServiceCmHandle.getCompositeState())); return restOutputCmHandle; } diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/mapper/RestOutputCmHandleStateMapper.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/mapper/CmHandleStateMapper.java similarity index 92% rename from cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/mapper/RestOutputCmHandleStateMapper.java rename to cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/mapper/CmHandleStateMapper.java index afad1098c..933ca88c9 100644 --- a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/mapper/RestOutputCmHandleStateMapper.java +++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/mapper/CmHandleStateMapper.java @@ -26,17 +26,17 @@ import org.mapstruct.Named; import org.mapstruct.NullValueCheckStrategy; import org.mapstruct.NullValuePropertyMappingStrategy; import org.onap.cps.ncmp.api.inventory.CompositeState; +import org.onap.cps.ncmp.rest.model.CmHandleCompositeState; import org.onap.cps.ncmp.rest.model.DataStores; -import org.onap.cps.ncmp.rest.model.RestOutputCmHandleState; import org.onap.cps.ncmp.rest.model.SyncState; @Mapper(componentModel = "spring", nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS, nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.SET_TO_DEFAULT) -public interface RestOutputCmHandleStateMapper { +public interface CmHandleStateMapper { @Mapping(target = "dataSyncState", source = "dataStores", qualifiedByName = "dataStoreToDataSyncState") @Mapping(target = "lockReason.reason", source = "lockReason.lockReasonCategory") - RestOutputCmHandleState toRestOutputCmHandleState(CompositeState compositeState); + CmHandleCompositeState toCmHandleCompositeState(CompositeState compositeState); /** * Convert from CompositeState datastore to RestOutput Datastores. diff --git a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy index 71258102e..93d8358fe 100644 --- a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy +++ b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy @@ -27,8 +27,9 @@ import org.mapstruct.factory.Mappers import org.onap.cps.ncmp.api.inventory.CmHandleState import org.onap.cps.ncmp.api.inventory.CompositeState import org.onap.cps.ncmp.api.inventory.SyncState +import org.onap.cps.ncmp.api.inventory.LockReasonCategory import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle -import org.onap.cps.ncmp.rest.mapper.RestOutputCmHandleStateMapper +import org.onap.cps.ncmp.rest.mapper.CmHandleStateMapper import org.onap.cps.ncmp.rest.executor.CpsNcmpTaskExecutor import org.onap.cps.ncmp.rest.util.DeprecationHelper import spock.lang.Shared @@ -40,7 +41,6 @@ import java.time.format.DateTimeFormatter import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.PATCH import static org.onap.cps.ncmp.api.inventory.CompositeState.DataStores import static org.onap.cps.ncmp.api.inventory.CompositeState.Operational -import static org.onap.cps.ncmp.api.inventory.CompositeState.Running import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch @@ -83,7 +83,7 @@ class NetworkCmProxyControllerSpec extends Specification { NcmpRestInputMapper ncmpRestInputMapper = Mappers.getMapper(NcmpRestInputMapper) @SpringBean - RestOutputCmHandleStateMapper restOutputCmHandleStateMapper = Mappers.getMapper(RestOutputCmHandleStateMapper) + CmHandleStateMapper cmHandleStateMapper = Mappers.getMapper(CmHandleStateMapper) @SpringBean CpsNcmpTaskExecutor spiedCpsTaskExecutor = Spy() @@ -262,24 +262,27 @@ class NetworkCmProxyControllerSpec extends Specification { response.contentAsString == '[{"cmHandle":"some-cmhandle-id1","publicCmHandleProperties":[{"color":"yellow"}],"state":null},{"cmHandle":"some-cmhandle-id2","publicCmHandleProperties":[{"color":"green"}],"state":null}]' } - def 'Get Cm Handle details by Cm Handle id.'() { + def 'Get complete Cm Handle details by Cm Handle id.'() { given: 'an endpoint and a cm handle' def cmHandleDetailsEndpoint = "$ncmpBasePathV1/ch/some-cm-handle" and: 'an existing ncmp service cm handle' - def compositeState = new CompositeState(cmHandleState: CmHandleState.ADVISED, - lastUpdateTime: formattedDateAndTime.toString(), - dataStores: dataStores()) - def ncmpServiceCmHandle = new NcmpServiceCmHandle(cmHandleId: 'some-cm-handle', compositeState: compositeState) + def cmHandleId = 'some-cm-handle' + def dmiProperties = [ prop:'some DMI property' ] + def publicProperties = [ "public prop":'some public property' ] + def compositeState = compositeStateTestObject() + def ncmpServiceCmHandle = new NcmpServiceCmHandle(cmHandleId: cmHandleId, dmiProperties: dmiProperties, publicProperties: publicProperties, compositeState: compositeState) and: 'the service method is invoked with the cm handle id' 1 * mockNetworkCmProxyDataService.getNcmpServiceCmHandle('some-cm-handle') >> ncmpServiceCmHandle when: 'the cm handle details api is invoked' def response = mvc.perform(get(cmHandleDetailsEndpoint)).andReturn().response then: 'the correct response is returned' response.status == HttpStatus.OK.value() - and: 'the response returns the correct state and timestamp' - response.contentAsString.contains('some-cm-handle') - response.contentAsString.contains('ADVISED') - response.contentAsString.contains('2022-12-31T20:30:40.000+0000') + and: 'the response contains the public properties' + assertContainsPublicProperties(response) + and: 'the response contains the cm handle state' + assertContainsState(response) + and: 'the content does not contain dmi properties' + !response.contentAsString.contains("some DMI property") } def 'Get Cm Handle public properties by Cm Handle id.' () { @@ -293,8 +296,23 @@ class NetworkCmProxyControllerSpec extends Specification { def response = mvc.perform(get(cmHandlePropertiesEndpoint)).andReturn().response then: 'the correct response is returned' response.status == HttpStatus.OK.value() - and: 'the response returns public properties and the correct properties' - response.contentAsString.equals('{"publicCmHandleProperties":[{"public prop":"some public property"}]}') + and: 'the response contains the public properties' + assertContainsPublicProperties(response) + } + + def 'Get Cm Handle composite state by Cm Handle id.' () { + given: 'a cm handle state endpoint' + def cmHandlePropertiesEndpoint = "$ncmpBasePathV1/ch/some-cm-handle/state" + and: 'some cm handle composite state' + def compositeState = compositeStateTestObject() + and: 'the service method is invoked with the cm handle id returning the cm handle composite state' + 1 * mockNetworkCmProxyDataService.getCmHandleCompositeState('some-cm-handle') >> compositeState + when: 'the cm handle state api is invoked' + def response = mvc.perform(get(cmHandlePropertiesEndpoint)).andReturn().response + then: 'the correct response is returned' + response.status == HttpStatus.OK.value() + and: 'the response contains the cm handle state' + assertContainsState(response) } def 'Call execute cm handle searches with unrecognized condition name.'() { @@ -397,5 +415,44 @@ class NetworkCmProxyControllerSpec extends Specification { .lastSyncTime(formattedDateAndTime.toString()).build()).build() } + def compositeStateTestObject() { + new CompositeState(cmHandleState: CmHandleState.ADVISED, + lockReason: CompositeState.LockReason.builder().lockReasonCategory(LockReasonCategory.LOCKED_MISBEHAVING).details("lock misbehaving details").build(), + lastUpdateTime: formattedDateAndTime.toString(), + dataSyncEnabled: false, + dataStores: dataStores()) + } + + def assertContainsAll(response, assertContent) { + assertContent.forEach( string -> { assert(response.contentAsString.contains(string)) }) + return void + } + + def assertContainsState(response) { + def expectedContent = [ + '"state":', + '"cmHandleState":"ADVISED"', + '"reason":"LOCKED_MISBEHAVING"', + '"details":"lock misbehaving details"', + '"lastUpdateTime":"2022-12-31T20:30:40.000+0000"', + '"dataSyncEnabled":false', + '"dataSyncState":', + '"operational":', + '"state":"NONE_REQUESTED"', + '"lastSyncTime":"2022-12-31T20:30:40.000+0000"', + '"running":null' + ] + return assertContainsAll(response, expectedContent) + } + + def assertContainsPublicProperties(response) { + def expectedContent = [ + '"publicCmHandleProperties":' , + '"public prop"' , + '"some public property"' + ] + return assertContainsAll(response, expectedContent) + } + } diff --git a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandlerSpec.groovy b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandlerSpec.groovy index 1563c75b3..ce908e754 100644 --- a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandlerSpec.groovy +++ b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandlerSpec.groovy @@ -29,7 +29,7 @@ import org.onap.cps.ncmp.api.impl.exception.DmiRequestException import org.onap.cps.ncmp.api.impl.exception.HttpClientRequestException import org.onap.cps.ncmp.api.impl.exception.ServerNcmpException import org.onap.cps.ncmp.rest.controller.NcmpRestInputMapper -import org.onap.cps.ncmp.rest.mapper.RestOutputCmHandleStateMapper +import org.onap.cps.ncmp.rest.mapper.CmHandleStateMapper import org.onap.cps.ncmp.rest.executor.CpsNcmpTaskExecutor import org.onap.cps.ncmp.rest.util.DeprecationHelper import org.onap.cps.spi.exceptions.CpsException @@ -70,7 +70,7 @@ class NetworkCmProxyRestExceptionHandlerSpec extends Specification { NcmpRestInputMapper ncmpRestInputMapper = Mappers.getMapper(NcmpRestInputMapper) @SpringBean - RestOutputCmHandleStateMapper restOutputCmHandleStateMapper = Mappers.getMapper(RestOutputCmHandleStateMapper) + CmHandleStateMapper cmHandleStateMapper = Mappers.getMapper(CmHandleStateMapper) @SpringBean CpsNcmpTaskExecutor stubbedCpsTaskExecutor = Stub() diff --git a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/mapper/RestOutputCmHandleStateMapperTest.groovy b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/mapper/CmHandleStateMapperTest.groovy similarity index 88% rename from cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/mapper/RestOutputCmHandleStateMapperTest.groovy rename to cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/mapper/CmHandleStateMapperTest.groovy index 695ca5ad6..a6c1278d9 100644 --- a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/mapper/RestOutputCmHandleStateMapperTest.groovy +++ b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/mapper/CmHandleStateMapperTest.groovy @@ -25,18 +25,18 @@ import org.onap.cps.ncmp.api.inventory.CmHandleState import org.onap.cps.ncmp.api.inventory.CompositeStateBuilder import org.onap.cps.ncmp.api.inventory.LockReasonCategory import org.onap.cps.ncmp.api.inventory.SyncState -import org.onap.cps.ncmp.rest.model.RestOutputCmHandleState +import org.onap.cps.ncmp.rest.model.CmHandleCompositeState import spock.lang.Specification import java.time.OffsetDateTime import java.time.ZoneOffset import java.time.format.DateTimeFormatter -class RestOutputCmHandleStateMapperTest extends Specification { +class CmHandleStateMapperTest extends Specification { def formattedDateAndTime = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ") .format(OffsetDateTime.of(2022, 12, 31, 20, 30, 40, 1, ZoneOffset.UTC)) - def objectUnderTest = Mappers.getMapper(RestOutputCmHandleStateMapper) + def objectUnderTest = Mappers.getMapper(CmHandleStateMapper) def 'Composite State to Rest Output CmHandleState'() { given: 'a composite state model' @@ -47,9 +47,9 @@ class RestOutputCmHandleStateMapperTest extends Specification { .withOperationalDataStores(SyncState.SYNCHRONIZED, formattedDateAndTime).build() compositeState.setDataSyncEnabled(false) when: 'mapper is called' - def result = objectUnderTest.toRestOutputCmHandleState(compositeState) + def result = objectUnderTest.toCmHandleCompositeState(compositeState) then: 'result is of the correct type' - assert result.class == RestOutputCmHandleState.class + assert result.class == CmHandleCompositeState.class and: 'mapped result should have correct values' assert !result.dataSyncEnabled assert result.lastUpdateTime == formattedDateAndTime diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyDataService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyDataService.java index ce850cc82..1ad61e6a6 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyDataService.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyDataService.java @@ -28,6 +28,7 @@ import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum import java.util.Collection; import java.util.Map; import java.util.Set; +import org.onap.cps.ncmp.api.inventory.CompositeState; import org.onap.cps.ncmp.api.models.CmHandleQueryApiParameters; import org.onap.cps.ncmp.api.models.DmiPluginRegistration; import org.onap.cps.ncmp.api.models.DmiPluginRegistrationResponse; @@ -121,6 +122,14 @@ public interface NetworkCmProxyDataService { */ Map getCmHandlePublicProperties(String cmHandleId); + /** + * Get cm handle composite state by cm handle id. + * + * @param cmHandleId cm handle identifier + * @return a cm handle composite state + */ + CompositeState getCmHandleCompositeState(String cmHandleId); + /** * Query and return cm handles that match the given query parameters. * diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java index f44c28c71..bfc740786 100755 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java @@ -221,6 +221,18 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService return cmHandlePublicProperties; } + /** + * Get cm handle composite state for a given cm handle id. + * + * @param cmHandleId cm handle identifier + * @return cm handle state + */ + @Override + public CompositeState getCmHandleCompositeState(final String cmHandleId) { + CpsValidator.validateNameCharacters(cmHandleId); + return inventoryPersistence.getYangModelCmHandle(cmHandleId).getCompositeState(); + } + /** * THis method registers a cm handle and initiates modules sync. * diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy index 1d4312c68..92183f927 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy @@ -27,6 +27,8 @@ import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle import org.onap.cps.ncmp.api.inventory.CmHandleState import org.onap.cps.ncmp.api.inventory.CompositeState import org.onap.cps.ncmp.api.inventory.InventoryPersistence +import org.onap.cps.ncmp.api.inventory.LockReasonCategory +import org.onap.cps.ncmp.api.inventory.SyncState import org.onap.cps.ncmp.api.models.CmHandleQueryApiParameters import org.onap.cps.ncmp.api.models.ConditionApiProperties import org.onap.cps.ncmp.api.models.DmiPluginRegistration @@ -169,19 +171,29 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { def 'Get a cm handle.'() { given: 'the system returns a yang modelled cm handle' def dmiServiceName = 'some service name' + def compositeState = new CompositeState(cmHandleState: CmHandleState.ADVISED, + lockReason: CompositeState.LockReason.builder().lockReasonCategory(LockReasonCategory.LOCKED_MISBEHAVING).details("lock misbehaving details").build(), + lastUpdateTime: 'some-timestamp', + dataSyncEnabled: false, + dataStores: dataStores()) def dmiProperties = [new YangModelCmHandle.Property('Book', 'Romance Novel')] def publicProperties = [new YangModelCmHandle.Property('Public Book', 'Public Romance Novel')] - def compositeState = new CompositeState(cmHandleState: 'ADVISED') def yangModelCmHandle = new YangModelCmHandle(id: 'some-cm-handle', dmiServiceName: dmiServiceName, dmiProperties: dmiProperties, publicProperties: publicProperties, compositeState: compositeState) 1 * mockInventoryPersistence.getYangModelCmHandle('some-cm-handle') >> yangModelCmHandle when: 'getting cm handle details for a given cm handle id from ncmp service' def result = objectUnderTest.getNcmpServiceCmHandle('some-cm-handle') - then: 'the result returns the correct data' + then: 'the result is a ncmpServiceCmHandle' + result.class == NcmpServiceCmHandle.class + and: 'the cm handle contains the cm handle id' result.cmHandleId == 'some-cm-handle' + and: 'the cm handle contains the DMI Properties' result.dmiProperties ==[ Book:'Romance Novel' ] + and: 'the cm handle contains the public Properties' result.publicProperties == [ "Public Book":'Public Romance Novel' ] - result.compositeState.cmHandleState == CmHandleState.ADVISED + and: 'the cm handle contains the cm handle composite state' + result.compositeState == compositeState + } def 'Get a cm handle with an invalid id.'() { @@ -207,7 +219,7 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { } def 'Get cm handle public properties with an invalid id.'() { - when: 'getting cm handle details for a given cm handle id with an invalid name' + when: 'getting cm handle public properties for a given cm handle id with an invalid name' objectUnderTest.getCmHandlePublicProperties('invalid cm handle with spaces') then: 'an exception is thrown' thrown(DataValidationException) @@ -215,6 +227,33 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { 0 * mockInventoryPersistence.getYangModelCmHandle(*_) } + def 'Get cm handle composite state'() { + given: 'a yang modelled cm handle' + def compositeState = new CompositeState(cmHandleState: CmHandleState.ADVISED, + lockReason: CompositeState.LockReason.builder().lockReasonCategory(LockReasonCategory.LOCKED_MISBEHAVING).details("lock misbehaving details").build(), + lastUpdateTime: 'some-timestamp', + dataSyncEnabled: false, + dataStores: dataStores()) + def dmiProperties = [new YangModelCmHandle.Property('prop', 'some DMI property')] + def publicProperties = [new YangModelCmHandle.Property('public prop', 'some public prop')] + def yangModelCmHandle = new YangModelCmHandle(id:'some-cm-handle', dmiServiceName: 'some service name', dmiProperties: dmiProperties, publicProperties: publicProperties, compositeState: compositeState) + and: 'the system returns this yang modelled cm handle' + 1 * mockInventoryPersistence.getYangModelCmHandle('some-cm-handle') >> yangModelCmHandle + when: 'getting cm handle composite state for a given cm handle id from ncmp service' + def result = objectUnderTest.getCmHandleCompositeState('some-cm-handle') + then: 'the result returns the correct data' + result == compositeState + } + + def 'Get cm handle composite state with an invalid id.'() { + when: 'getting cm handle composite state for a given cm handle id with an invalid name' + objectUnderTest.getCmHandleCompositeState('invalid cm handle with spaces') + then: 'an exception is thrown' + thrown(DataValidationException) + and: 'the yang model cm handle retriever is not invoked' + 0 * mockInventoryPersistence.getYangModelCmHandle(_) + } + def 'Update resource data for pass-through running from dmi using POST #scenario DMI properties.'() { given: 'cpsDataService returns valid datanode' mockCpsDataService.getDataNode('NCMP-Admin', 'ncmp-dmi-registry', @@ -265,4 +304,11 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { then: 'result is the same collection as returned by the CPS Data Service' assert result == ['cm-handle-id-1'] as Set } + + def dataStores() { + CompositeState.DataStores.builder() + .operationalDataStore(CompositeState.Operational.builder() + .syncState(SyncState.NONE_REQUESTED) + .lastSyncTime('some-timestamp').build()).build() + } } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/YangModelCmHandleSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/YangModelCmHandleSpec.groovy index 438ebed8f..cf9c6bbcf 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/YangModelCmHandleSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/YangModelCmHandleSpec.groovy @@ -21,6 +21,10 @@ package org.onap.cps.ncmp.api.models import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle +import org.onap.cps.ncmp.api.inventory.CmHandleState +import org.onap.cps.ncmp.api.inventory.CompositeStateBuilder +import org.onap.cps.ncmp.api.inventory.LockReasonCategory +import org.onap.cps.ncmp.api.inventory.SyncState import spock.lang.Specification import static org.onap.cps.ncmp.api.impl.operations.RequiredDmiService.DATA @@ -34,6 +38,13 @@ class YangModelCmHandleSpec extends Specification { ncmpServiceCmHandle.cmHandleId = 'cm-handle-id01' ncmpServiceCmHandle.dmiProperties = [myDmiProperty:'value1'] ncmpServiceCmHandle.publicProperties = [myPublicProperty:'value2'] + and: 'with a composite state' + def compositeState = new CompositeStateBuilder() + .withCmHandleState(CmHandleState.LOCKED) + .withLastUpdatedTime('some-update-time') + .withLockReason(LockReasonCategory.LOCKED_MISBEHAVING, 'locked other details') + .withOperationalDataStores(SyncState.SYNCHRONIZED, 'some-sync-time').build() + ncmpServiceCmHandle.setCompositeState(compositeState) when: 'it is converted to a yang model cm handle' def objectUnderTest = YangModelCmHandle.toYangModelCmHandle('', '', '', ncmpServiceCmHandle) then: 'the result has the right size' @@ -44,6 +55,9 @@ class YangModelCmHandleSpec extends Specification { and: 'the public property in the result has the correct name and value' assert objectUnderTest.publicProperties[0].name == 'myPublicProperty' assert objectUnderTest.publicProperties[0].value == 'value2' + and: 'the composite state matches the composite state of the ncmpServiceCmHandle' + objectUnderTest.getCompositeState().cmHandleState == CmHandleState.LOCKED + objectUnderTest.getCompositeState() == ncmpServiceCmHandle.getCompositeState() } def 'Resolve DMI service name: #scenario and #requiredService service require.'() {