ClassNameIdGetDataNodeSelectorParameter dataNodeSelector
);
+ /**
+ * DELETE /{URI-LDN-first-part}/{className}={id} : Deletes one resource
+ * With HTTP DELETE one resource is deleted. The resources to be deleted is identified with the target URI.
+ *
+ * @param httpServletRequest (required)
+ * @return Success case "200 OK". This status code is returned, when the resource has been successfully deleted.
+ * The response body is empty. (status code 200)
+ */
+ @Operation(
+ operationId = "deleteMoi",
+ summary = "Deletes one resource",
+ description = "With HTTP DELETE one resource is deleted. "
+ + "The resources to be deleted is identified with the target URI.",
+ responses = {
+ @ApiResponse(responseCode = "200",
+ description = "Success case (\"200 OK\"). This status code is returned, "
+ + "when the resource has been successfully deleted. The response body is empty."),
+ @ApiResponse(responseCode = "422", description = "Invalid Path Exception", content = {
+ @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorMessage.class))
+ }),
+ @ApiResponse(responseCode = "default", description = "Error case.", content = {
+ @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponseDefault.class))
+ })
+ }
+ )
+ @DeleteMapping(
+ value = "v1/**",
+ produces = { "application/json" }
+ )
+ ResponseEntity<Object> deleteMoi(HttpServletRequest httpServletRequest);
/**
* PATCH /{URI-LDN-first-part}/{className}={id} : Patches one or multiple resources
@PatchMapping(
value = "v1/**",
produces = { "application/json" },
- consumes = {"application/json-patch+json", "application/3gpp-json-patch+json" }
+ consumes = { "application/json-patch+json", "application/3gpp-json-patch+json" }
)
ResponseEntity<Resource> patchMoi(
@Valid @RequestBody Resource resource
);
- /**
- * DELETE /{URI-LDN-first-part}/{className}={id} : Deletes one resource
- * With HTTP DELETE one resource is deleted. The resources to be deleted is identified with the target URI.
- *
- * @param httpServletRequest (required)
- * @return Success case "200 OK". This status code is returned, when the resource has been successfully deleted.
- * The response body is empty. (status code 200)
- * or Error case. (status code 200)
- */
- @Operation(
- operationId = "deleteMoi",
- summary = "Deletes one resource",
- description = "With HTTP DELETE one resource is deleted. "
- + "The resources to be deleted is identified with the target URI.",
- responses = {
- @ApiResponse(responseCode = "200",
- description = "Success case (\"200 OK\"). This status code is returned, "
- + "when the resource has been successfully deleted. The response body is empty."),
- @ApiResponse(responseCode = "422", description = "Invalid Path Exception", content = {
- @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorMessage.class))
- }),
- @ApiResponse(responseCode = "default", description = "Error case.", content = {
- @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponseDefault.class))
- })
- }
- )
- @DeleteMapping(
- value = "v1/**",
- produces = { "application/json" }
- )
- ResponseEntity<Void> deleteMoi(HttpServletRequest httpServletRequest);
-
}
\ No newline at end of file
package org.onap.cps.ncmp.rest.controller;
-
import jakarta.servlet.http.HttpServletRequest;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.onap.cps.ncmp.api.data.models.OperationType;
+import org.onap.cps.ncmp.impl.data.policyexecutor.PolicyExecutor;
import org.onap.cps.ncmp.impl.dmi.DmiRestClient;
import org.onap.cps.ncmp.impl.inventory.InventoryPersistence;
import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
import org.onap.cps.ncmp.impl.provmns.model.Resource;
import org.onap.cps.ncmp.impl.provmns.model.Scope;
import org.onap.cps.ncmp.impl.utils.AlternateIdMatcher;
+import org.onap.cps.ncmp.impl.utils.http.RestServiceUrlTemplateBuilder;
import org.onap.cps.ncmp.impl.utils.http.UrlTemplateParameters;
+import org.onap.cps.ncmp.rest.provmns.model.ConfigurationManagementDeleteInput;
import org.onap.cps.ncmp.rest.util.ProvMnSParametersMapper;
import org.onap.cps.ncmp.rest.util.ProvMnsRequestParameters;
+import org.onap.cps.utils.JsonObjectMapper;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
@RequiredArgsConstructor
public class ProvMnsController implements ProvMnS {
+ private static final String NO_AUTHORIZATION = null;
private final AlternateIdMatcher alternateIdMatcher;
private final DmiRestClient dmiRestClient;
private final InventoryPersistence inventoryPersistence;
+ private final PolicyExecutor policyExecutor;
private final ProvMnSParametersMapper provMnsParametersMapper;
+ private final JsonObjectMapper jsonObjectMapper;
@Override
public ResponseEntity<Resource> getMoi(final HttpServletRequest httpServletRequest, final Scope scope,
public ResponseEntity<Resource> patchMoi(final HttpServletRequest httpServletRequest, final Resource resource) {
final ProvMnsRequestParameters requestParameters =
ProvMnsRequestParameters.extractProvMnsRequestParameters(httpServletRequest);
+ //TODO: implement if a different user sotry
+ // final ProvMnsRequestParameters requestParameters =
+ // ProvMnsRequestParameters.extractProvMnsRequestParameters(httpServletRequest);
return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
}
}
@Override
- public ResponseEntity<Void> deleteMoi(final HttpServletRequest httpServletRequest) {
- final ProvMnsRequestParameters requestParameters =
+ public ResponseEntity<Object> deleteMoi(final HttpServletRequest httpServletRequest) {
+ final ProvMnsRequestParameters provMnsRequestParameters =
ProvMnsRequestParameters.extractProvMnsRequestParameters(httpServletRequest);
- return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+
+ final String cmHandleId = alternateIdMatcher.getCmHandleId(provMnsRequestParameters.getFullUriLdn());
+ final YangModelCmHandle yangModelCmHandle = inventoryPersistence.getYangModelCmHandle(cmHandleId);
+
+ //TODO: implement if a different user story
+ //if (!yangModelCmHandle.getDataProducerIdentifier().isEmpty()
+ // && CmHandleState.READY == yangModelCmHandle.getCompositeState().getCmHandleState()) {
+
+ final ConfigurationManagementDeleteInput configurationManagementDeleteInput =
+ new ConfigurationManagementDeleteInput(OperationType.DELETE.name(),
+ provMnsRequestParameters.getFullUriLdn());
+
+ policyExecutor.checkPermission(yangModelCmHandle,
+ OperationType.DELETE,
+ NO_AUTHORIZATION,
+ provMnsRequestParameters.getFullUriLdn(),
+ jsonObjectMapper.asJsonString(configurationManagementDeleteInput));
+
+ final UrlTemplateParameters urlTemplateParameters = RestServiceUrlTemplateBuilder.newInstance()
+ .fixedPathSegment(configurationManagementDeleteInput.targetIdentifier())
+ .createUrlTemplateParameters(yangModelCmHandle.getDmiServiceName(),
+ "/ProvMnS");
+
+ return dmiRestClient.synchronousDeleteOperation(RequiredDmiService.DATA, urlTemplateParameters);
}
}
--- /dev/null
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2025 OpenInfra Foundation Europe
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.ncmp.rest.provmns.model;
+
+public record ConfigurationManagementDeleteInput (String operationType, String targetIdentifier) {}
\ No newline at end of file
@Setter
public class ProvMnsRequestParameters {
+ private String fullUriLdn;
private String uriLdnFirstPart;
private String className;
private String id;
throw new InvalidPathException(uriPath);
}
final ProvMnsRequestParameters provMnsRequestParameters = new ProvMnsRequestParameters();
+ provMnsRequestParameters.setFullUriLdn("/" + pathVariables[1]);
provMnsRequestParameters.setUriLdnFirstPart(pathVariables[1].substring(0, lastSlashIndex));
final String classNameAndId = pathVariables[1].substring(lastSlashIndex + 1);
import org.onap.cps.ncmp.impl.data.NcmpCachedResourceRequestHandler
import org.onap.cps.ncmp.impl.data.NcmpPassthroughResourceRequestHandler
import org.onap.cps.ncmp.impl.data.NetworkCmProxyFacade
+import org.onap.cps.ncmp.impl.data.policyexecutor.PolicyExecutor
import org.onap.cps.ncmp.impl.dmi.DmiRestClient
import org.onap.cps.ncmp.impl.inventory.InventoryPersistence
import org.onap.cps.ncmp.impl.utils.AlternateIdMatcher
@SpringBean
DmiRestClient dmiRestClient = Mock()
+ @SpringBean
+ PolicyExecutor policyExecutor = Mock()
+
@Value('${rest.api.ncmp-base-path}')
def basePathNcmp
import com.fasterxml.jackson.databind.ObjectMapper
import jakarta.servlet.ServletException
+import org.onap.cps.ncmp.api.data.models.OperationType
+import org.onap.cps.ncmp.api.inventory.models.CompositeStateBuilder
+import org.onap.cps.ncmp.impl.data.policyexecutor.PolicyExecutor
import org.onap.cps.ncmp.impl.dmi.DmiRestClient
import org.onap.cps.ncmp.impl.inventory.InventoryPersistence
import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle
import org.springframework.test.web.servlet.MockMvc
import spock.lang.Specification
+import static org.onap.cps.ncmp.api.inventory.models.CmHandleState.READY
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
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put
@WebMvcTest(ProvMnsController)
class ProvMnsControllerSpec extends Specification {
@SpringBean
InventoryPersistence inventoryPersistence = Mock()
+ @SpringBean
+ PolicyExecutor policyExecutor = Mock()
+
@SpringBean
DmiRestClient dmiRestClient = Mock()
@Autowired
MockMvc mvc
- def jsonObjectMapper = new JsonObjectMapper(new ObjectMapper())
+ @SpringBean
+ JsonObjectMapper jsonObjectMapper = new JsonObjectMapper(new ObjectMapper())
@Value('${rest.api.provmns-base-path}')
def provMnSBasePath
def 'Put Resource Data from provmns interface.'() {
given: 'resource data url'
def putUrl = "$provMnSBasePath/v1/someUriLdnFirstPart/someClassName=someId"
- and: 'an example resource json object'
- def jsonBody = jsonObjectMapper.asJsonString(new ResourceOneOf('test'))
- when: 'put data resource request is performed'
- def response = mvc.perform(put(putUrl)
- .contentType(MediaType.APPLICATION_JSON)
+ and: 'a valid json body containing a valid Resource instance'
+ def jsonBody = '{ "id": "some-resource" }'
+ when: 'patch data resource request is performed'
+ def response = mvc.perform(patch(putUrl)
+ .contentType(new MediaType('application', 'json-patch+json'))
.content(jsonBody))
.andReturn().response
then: 'response status is Not Implemented (501)'
def 'Delete Resource Data from provmns interface.'() {
given: 'resource data url'
- def deleteUrl = "$provMnSBasePath/v1/someUriLdnFirstPart/someClassName=someId"
+ def deleteUrl = "$provMnSBasePath/v1/someLdnFirstPart/someClass=someId"
+ def readyState = new CompositeStateBuilder().withCmHandleState(READY).withLastUpdatedTimeNow().build()
+ and: 'a cm handle found by alternate id and dmi returns a response'
+ alternateIdMatcher.getCmHandleId("/someLdnFirstPart/someClass=someId") >> "cm-1"
+ inventoryPersistence.getYangModelCmHandle("cm-1") >> new YangModelCmHandle(dmiServiceName: 'sampleDmiService', dataProducerIdentifier: 'some-producer', compositeState: readyState)
+ dmiRestClient.synchronousDeleteOperation(*_) >> new ResponseEntity<>('Response from DMI service', HttpStatus.I_AM_A_TEAPOT)
+ and: 'the policy executor invoked'
+ 1 * policyExecutor.checkPermission(_, OperationType.DELETE, null, '/someLdnFirstPart/someClass=someId', _)
when: 'delete data resource request is performed'
- def response = mvc.perform(delete(deleteUrl)).andReturn().response
- then: 'response status is Not Implemented (501)'
- assert response.status == HttpStatus.NOT_IMPLEMENTED.value()
+ def result = mvc.perform(delete(deleteUrl)).andReturn().response
+ then: 'result status and content equals the response from the DMI'
+ assert result.status == HttpStatus.I_AM_A_TEAPOT.value()
+ assert result.contentAsString == 'Response from DMI service'
}
def 'Invalid path passed in to provmns interface, #scenario'() {
.retrieve()
.bodyToMono(JsonNode.class)
.map(responseHealthStatus -> responseHealthStatus.path("status").asText())
- .onErrorResume(Exception.class, ex -> {
+ .onErrorResume(Exception.class, e -> {
log.warn("Failed to retrieve health status from {}. Status: {}",
- urlTemplateParameters.urlTemplate(), ex.getMessage());
+ urlTemplateParameters.urlTemplate(), e.getMessage());
return Mono.empty();
})
.defaultIfEmpty(NOT_SPECIFIED);
public Mono<String> getDataJobResult(final UrlTemplateParameters urlTemplateParameters,
final String authorization) {
return dataServicesWebClient.get()
- .uri(urlTemplateParameters.urlTemplate(), urlTemplateParameters.urlVariables())
- .headers(httpHeaders -> configureHttpHeaders(httpHeaders, authorization))
- .retrieve().bodyToMono(String.class)
- .onErrorMap(throwable -> handleDmiClientException(throwable,
- OperationType.READ.getOperationName()));
+ .uri(urlTemplateParameters.urlTemplate(), urlTemplateParameters.urlVariables())
+ .headers(httpHeaders -> configureHttpHeaders(httpHeaders, authorization))
+ .retrieve().bodyToMono(String.class)
+ .onErrorMap(throwable -> handleDmiClientException(throwable, OperationType.READ.getOperationName()));
+ }
+
+ /**
+ * Sends a synchronous (blocking) DELETE operation to the DMI with a JSON body.
+ *
+ * @param requiredDmiService Determines if the required service is for a data or model operation.
+ * @param urlTemplateParameters The DMI resource URL template with variables.
+ * @return ResponseEntity from the DMI Plugin
+ * @throws DmiClientRequestException If there is an error during the DMI request.
+ *
+ */
+ public ResponseEntity<Object> synchronousDeleteOperation(final RequiredDmiService requiredDmiService,
+ final UrlTemplateParameters urlTemplateParameters) {
+ return getWebClient(requiredDmiService)
+ .delete()
+ .uri(urlTemplateParameters.urlTemplate(), urlTemplateParameters.urlVariables())
+ .headers(httpHeaders -> configureHttpHeaders(httpHeaders, NO_AUTHORIZATION))
+ .retrieve()
+ .toEntity(Object.class)
+ .onErrorMap(throwable -> handleDmiClientException(throwable, OperationType.DELETE.getOperationName()))
+ .block();
}
private WebClient getWebClient(final RequiredDmiService requiredDmiService) {
def mockModelServicesWebClient = Mock(WebClient)
def mockHealthChecksWebClient = Mock(WebClient)
- def mockRequestBody = Mock(WebClient.RequestBodyUriSpec)
- def mockResponse = Mock(WebClient.ResponseSpec)
+ def mockRequestBodyUriSpec = Mock(WebClient.RequestBodyUriSpec)
+ def mockResponseSpec = Mock(WebClient.ResponseSpec)
def mockDmiServiceAuthenticationProperties = Mock(DmiServiceAuthenticationProperties)
JsonObjectMapper jsonObjectMapper = new JsonObjectMapper(new ObjectMapper())
+ def responseFromDmiService = new ResponseEntity<>('Response from DMI service', HttpStatus.I_AM_A_TEAPOT)
DmiRestClient objectUnderTest = new DmiRestClient(mockDmiServiceAuthenticationProperties, jsonObjectMapper, mockDataServicesWebClient, mockModelServicesWebClient, mockHealthChecksWebClient)
def setup() {
- mockRequestBody.uri(_,_) >> mockRequestBody
- mockRequestBody.headers(_) >> mockRequestBody
- mockRequestBody.body(_) >> mockRequestBody
- mockRequestBody.retrieve() >> mockResponse
+ mockRequestBodyUriSpec.uri(*_) >> mockRequestBodyUriSpec
+ mockRequestBodyUriSpec.headers(_) >> mockRequestBodyUriSpec
+ mockRequestBodyUriSpec.body(_) >> mockRequestBodyUriSpec
+ mockRequestBodyUriSpec.retrieve() >> mockResponseSpec
}
- def 'DMI POST Operation with JSON for DMI Data Service '() {
+ def 'DMI POST Operation with JSON for DMI Data Service.'() {
given: 'the Data web client returns a valid response entity for the expected parameters'
- mockDataServicesWebClient.post() >> mockRequestBody
- mockResponse.toEntity(Object.class) >> Mono.just(new ResponseEntity<>('from Data service', HttpStatus.I_AM_A_TEAPOT))
- when: 'POST operation is invoked fro Data Service'
- def response = objectUnderTest.synchronousPostOperation(DATA, urlTemplateParameters, 'some json', READ, NO_AUTH_HEADER)
- then: 'the output of the method is equal to the output from the test template'
- assert response.statusCode == HttpStatus.I_AM_A_TEAPOT
- assert response.body == 'from Data service'
+ mockDataServicesWebClient.post() >> mockRequestBodyUriSpec
+ mockResponseSpec.toEntity(Object.class) >> Mono.just(responseFromDmiService)
+ when: 'POST operation is invoked for Data Service'
+ def result = objectUnderTest.synchronousPostOperation(DATA, urlTemplateParameters, 'some json', READ, NO_AUTH_HEADER)
+ then: 'the output of the method is equal to the output from dmi service'
+ assert result.equals(responseFromDmiService)
}
- def 'DMI POST Operation with JSON for DMI Model Service '() {
+ def 'DMI POST Operation with JSON for DMI Model Service.'() {
given: 'the Model web client returns a valid response entity for the expected parameters'
- mockModelServicesWebClient.post() >> mockRequestBody
- mockResponse.toEntity(Object.class) >> Mono.just(new ResponseEntity<>('from Model service', HttpStatus.I_AM_A_TEAPOT))
+ mockModelServicesWebClient.post() >> mockRequestBodyUriSpec
+ mockResponseSpec.toEntity(Object.class) >> Mono.just(responseFromDmiService)
when: 'POST operation is invoked for Model Service'
- def response = objectUnderTest.synchronousPostOperation(MODEL, urlTemplateParameters, 'some json', READ, NO_AUTH_HEADER)
- then: 'the output of the method is equal to the output from the test template'
- assert response.statusCode == HttpStatus.I_AM_A_TEAPOT
- assert response.body == 'from Model service'
+ def result = objectUnderTest.synchronousPostOperation(MODEL, urlTemplateParameters, 'some json', READ, NO_AUTH_HEADER)
+ then: 'the output of the method is equal to the output from the dmi service'
+ assert result.equals(responseFromDmiService)
}
- def 'Dmi service sends client error response when #scenario'() {
+ def 'Synchronous DMI POST operation with #scenario.'() {
given: 'the web client unable to return response entity but error'
- mockDataServicesWebClient.post() >> mockRequestBody
- mockResponse.toEntity(Object.class) >> Mono.error(exceptionType)
+ mockDataServicesWebClient.post() >> mockRequestBodyUriSpec
+ mockResponseSpec.toEntity(Object.class) >> Mono.error(exception)
when: 'POST operation is invoked'
objectUnderTest.synchronousPostOperation(DATA, urlTemplateParameters, 'some json', READ, NO_AUTH_HEADER)
then: 'a http client exception is thrown'
assert thrown.ncmpResponseStatus == expectedNcmpResponseStatusCode
assert thrown.httpStatusCode == httpStatusCode
where: 'the following errors occur'
- scenario | httpStatusCode | exceptionType || expectedNcmpResponseStatusCode
+ scenario | httpStatusCode | exception || expectedNcmpResponseStatusCode
'dmi service unavailable' | 503 | new WebClientRequestException(new RuntimeException('some-error'), null, null, new HttpHeaders()) || DMI_SERVICE_NOT_RESPONDING
'dmi request timeout' | 408 | new WebClientResponseException('message', httpStatusCode, 'statusText', null, null, null) || DMI_SERVICE_NOT_RESPONDING
'dmi server error' | 500 | new WebClientResponseException('message', httpStatusCode, 'statusText', null, null, null) || UNABLE_TO_READ_RESOURCE_DATA
'unknown error' | 500 | new Throwable('message') || UNKNOWN_ERROR
}
- def 'Dmi trust level is determined by spring boot health status'() {
+ def 'Synchronous DMI GET Operation.'() {
+ given: 'the Data web client returns a valid response entity for the expected parameters'
+ mockDataServicesWebClient.get() >> mockRequestBodyUriSpec
+ mockResponseSpec.toEntity(_) >> Mono.just(responseFromDmiService)
+ when: 'GET operation is invoked for Data Service'
+ def result = objectUnderTest.synchronousGetOperation(DATA, urlTemplateParameters, READ)
+ then: 'the output of the method is equal to the output from the DMI service'
+ assert result.equals(responseFromDmiService)
+ }
+
+ def 'Dmi trust level is determined by spring boot health status.'() {
given: 'a health check response'
def dmiPluginHealthCheckResponseJsonData = TestUtils.getResourceFileContent('dmiPluginHealthCheckResponse.json')
def jsonNode = jsonObjectMapper.convertJsonString(dmiPluginHealthCheckResponseJsonData, JsonNode.class)
((ObjectNode) jsonNode).put('status', 'my status')
- mockHealthChecksWebClient.get() >> mockRequestBody
- mockResponse.onStatus(_,_)>> mockResponse
- mockResponse.bodyToMono(JsonNode.class) >> Mono.just(jsonNode)
+ mockHealthChecksWebClient.get() >> mockRequestBodyUriSpec
+ mockResponseSpec.bodyToMono(JsonNode.class) >> Mono.just(jsonNode)
when: 'get trust level of the dmi plugin'
def urlTemplateParameters = new UrlTemplateParameters('some url', [:])
def result = objectUnderTest.getDmiHealthStatus(urlTemplateParameters).block()
assert result == 'my status'
}
- def 'Failing to get dmi plugin health status #scenario'() {
+ def 'Failing to get dmi plugin health status #scenario.'() {
given: 'web client instance with #scenario'
- mockHealthChecksWebClient.get() >> mockRequestBody
- mockResponse.onStatus(_, _) >> mockResponse
- mockResponse.bodyToMono(_) >> Mono.error(exceptionType)
+ mockHealthChecksWebClient.get() >> mockRequestBodyUriSpec
+ mockResponseSpec.bodyToMono(_) >> Mono.error(exceptionType)
when: 'attempt to get health status of the dmi plugin'
def urlTemplateParameters = new UrlTemplateParameters('some url', [:])
def result = objectUnderTest.getDmiHealthStatus(urlTemplateParameters).block()
'dmi service unavailable' | new HttpServerErrorException(HttpStatus.SERVICE_UNAVAILABLE)
}
- def 'DMI auth header #scenario'() {
+ def 'DMI auth header #scenario.'() {
when: 'Specific dmi properties are provided'
mockDmiServiceAuthenticationProperties.dmiBasicAuthEnabled >> authEnabled
mockDmiServiceAuthenticationProperties.authUsername >> 'some user'
'DMI basic auth disabled, with NCMP basic auth' | false | BASIC_AUTH_HEADER || NO_AUTH_HEADER
}
- def 'DMI GET Operation for DMI Data Service '() {
+ def 'DMI Data Job Status request for DMI Data Service.'() {
given: 'the Data web client returns a valid response entity for the expected parameters'
- mockDataServicesWebClient.get() >> mockRequestBody
- def result = '{"status":"some status"}'
- mockResponse.bodyToMono(String.class) >> Mono.just(result)
- when: 'GET operation is invoked for Data Service'
- def response = objectUnderTest.getDataJobStatus(urlTemplateParameters, NO_AUTH_HEADER).block()
- then: 'the response equals to the expected value'
- assert response == '{"status":"some status"}'
+ mockDataServicesWebClient.get() >> mockRequestBodyUriSpec
+ mockResponseSpec.bodyToMono(String.class) >> Mono.just(responseFromDmiService)
+ when: 'Data job status is invoked for Data Service'
+ def result = objectUnderTest.getDataJobStatus(urlTemplateParameters, NO_AUTH_HEADER).block()
+ then: 'the response equals to response from the DMI service'
+ assert result.equals(responseFromDmiService)
}
def 'Get data job result from DMI.'() {
given: 'the Data web client returns a valid response entity for the expected parameters'
- mockDataServicesWebClient.get() >> mockRequestBody
- def result = 'some result'
- mockResponse.bodyToMono(String.class) >> Mono.just(result)
+ mockDataServicesWebClient.get() >> mockRequestBodyUriSpec
+ mockResponseSpec.bodyToMono(String.class) >> Mono.just(responseFromDmiService)
when: 'GET operation is invoked for Data Service'
- def response = objectUnderTest.getDataJobResult(urlTemplateParameters, NO_AUTH_HEADER).block()
+ def result = objectUnderTest.getDataJobResult(urlTemplateParameters, NO_AUTH_HEADER).block()
then: 'the response has some value'
- assert response != null
- assert result == 'some result'
+ assert result.equals(responseFromDmiService)
+ }
+
+ def 'DMI DELETE Operation for DMI Data Service.'() {
+ given: 'the Data web client returns a valid response entity for the expected parameters'
+ mockDataServicesWebClient.delete() >> mockRequestBodyUriSpec
+ mockResponseSpec.toEntity(Object.class) >> Mono.just(responseFromDmiService)
+ when: 'DELETE operation is invoked for Data Service'
+ def result = objectUnderTest.synchronousDeleteOperation(DATA, urlTemplateParameters)
+ then: 'The response is the same as the response from the DMI service'
+ assert result.equals(responseFromDmiService)
}
}
<dependency.check.version>9.2.0</dependency.check.version>
<git.commit.id.version>9.0.1</git.commit.id.version>
<gmavenplus.plugin.version>4.0.1</gmavenplus.plugin.version>
- <jacoco.version>0.8.11</jacoco.version>
+ <jacoco.version>0.8.14</jacoco.version>
<java.version>17</java.version>
<jsonschema2pojo.maven.plugin.version>1.2.1</jsonschema2pojo.maven.plugin.version>
<maven.checkstyle.plugin.version>3.3.1</maven.checkstyle.plugin.version>
}
def 'Delete Resource Data from provmns interface.'() {
- expect: 'not implemented response on DELETE endpoint'
- mvc.perform(delete("/ProvMnS/v1/A=1/B=2/C=3"))
- .andExpect(status().isNotImplemented())
+ given: 'a registered cm handle'
+ dmiDispatcher1.moduleNamesPerCmHandleId['ch-1'] = ['M1', 'M2']
+ registerCmHandle(DMI1_URL, 'ch-1', NO_MODULE_SET_TAG, '/A=1/B=2/C=3')
+ expect: 'ok response on DELETE endpoint'
+ mvc.perform(delete("/ProvMnS/v1/A=1/B=2/C=3")).andExpect(status().isOk())
+ cleanup: 'deregister CM handles'
+ deregisterCmHandle(DMI1_URL, 'ch-1')
}
}