aboutsummaryrefslogtreecommitdiffstats
path: root/integration-test/src
diff options
context:
space:
mode:
Diffstat (limited to 'integration-test/src')
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy13
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/base/DmiDispatcher.groovy35
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/base/PolicyDispatcher.groovy74
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/DataServiceIntegrationSpec.groovy42
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/QueryServiceIntegrationSpec.groovy1
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/AlternateIdSpec.groovy54
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/CmHandleCreateSpec.groovy33
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/CmHandleUpdateSpec.groovy89
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/DataJobResultServiceSpec.groovy44
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/DataJobStatusServiceSpec.groovy5
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/PolicyExecutorIntegrationSpec.groovy63
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/RestApiSpec.groovy23
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/WriteSubJobSpec.groovy6
-rw-r--r--integration-test/src/test/resources/application.yml14
14 files changed, 453 insertions, 43 deletions
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy
index 5e46e95a0c..bd53c4ea13 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy
@@ -46,6 +46,7 @@ import org.onap.cps.spi.utils.SessionManager
import org.onap.cps.utils.ContentType
import org.onap.cps.utils.JsonObjectMapper
import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
import org.springframework.boot.autoconfigure.domain.EntityScan
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc
@@ -125,12 +126,19 @@ abstract class CpsIntegrationSpecBase extends Specification {
@Autowired
AlternateIdMatcher alternateIdMatcher
+
+ @Value('${ncmp.policy-executor.server.port:8080}')
+ private String policyServerPort;
+
MockWebServer mockDmiServer1 = new MockWebServer()
MockWebServer mockDmiServer2 = new MockWebServer()
+ MockWebServer mockPolicyServer = new MockWebServer()
DmiDispatcher dmiDispatcher1 = new DmiDispatcher()
DmiDispatcher dmiDispatcher2 = new DmiDispatcher()
+ PolicyDispatcher policyDispatcher = new PolicyDispatcher();
+
def DMI1_URL = null
def DMI2_URL = null
@@ -155,13 +163,18 @@ abstract class CpsIntegrationSpecBase extends Specification {
mockDmiServer2.setDispatcher(dmiDispatcher2)
mockDmiServer2.start()
+ mockPolicyServer.setDispatcher(policyDispatcher)
+ mockPolicyServer.start(Integer.valueOf(policyServerPort))
+
DMI1_URL = String.format("http://%s:%s", mockDmiServer1.getHostName(), mockDmiServer1.getPort())
DMI2_URL = String.format("http://%s:%s", mockDmiServer2.getHostName(), mockDmiServer2.getPort())
+
}
def cleanup() {
mockDmiServer1.shutdown()
mockDmiServer2.shutdown()
+ mockPolicyServer.shutdown()
}
def static readResourceDataFile(filename) {
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/base/DmiDispatcher.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/base/DmiDispatcher.groovy
index 5ce2475d7d..35a7b6a7c2 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/base/DmiDispatcher.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/base/DmiDispatcher.groovy
@@ -20,10 +20,7 @@
package org.onap.cps.integration.base
-import static org.onap.cps.integration.base.CpsIntegrationSpecBase.readResourceDataFile
-
import groovy.json.JsonSlurper
-import java.util.regex.Matcher
import okhttp3.mockwebserver.Dispatcher
import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.RecordedRequest
@@ -31,6 +28,10 @@ import org.springframework.http.HttpHeaders
import org.springframework.http.HttpStatus
import org.springframework.http.MediaType
+import java.util.regex.Matcher
+
+import static org.onap.cps.integration.base.CpsIntegrationSpecBase.readResourceDataFile
+
/**
* This class simulates responses from the DMI server in NCMP integration tests.
*
@@ -91,53 +92,57 @@ class DmiDispatcher extends Dispatcher {
case ~'^/dmi/v1/data$':
return mockResponseWithBody(HttpStatus.ACCEPTED, '{}')
- // get write sub job response
- case ~'^/dmi/v1/writeJob/(.*)$':
- return mockWriteJobResponse(request)
-
// get data job status
- case ~'^/dmi/v1/dataJob/(.*)/dataProducerJob/(.*)/status(.*)$':
+ case ~'^/dmi/v1/cmwriteJob/dataProducer/(.*)/dataProducerJob/(.*)/status$':
return mockResponseWithBody(HttpStatus.OK, '{"status":"status details from mock service"}')
+ // get data job result
+ case ~'^/dmi/v1/cmwriteJob/dataProducer/(.*)/dataProducerJob/(.*)/result(.*)$':
+ return mockResponseWithBody(HttpStatus.OK, '{ "result": "some result"}')
+
+ // get write sub job response
+ case ~'^/dmi/v1/cmwriteJob(.*)$':
+ return mockWriteJobResponse(request)
+
default:
throw new IllegalArgumentException('Mock DMI does not implement endpoint ' + request.path)
}
}
def mockWriteJobResponse(request) {
- def requestId = Matcher.lastMatcher[0][1]
+ def destination = Matcher.lastMatcher[0][1]
def subJobWriteRequest = jsonSlurper.parseText(request.getBody().readUtf8())
- this.receivedSubJobs.put(requestId, subJobWriteRequest)
+ this.receivedSubJobs.put(destination, subJobWriteRequest)
def response = '{"subJobId":"some sub job id", "dmiServiceName":"some dmi service name", "dataProducerId":"some data producer id"}'
return mockResponseWithBody(HttpStatus.OK, response)
}
- private getModuleReferencesResponse(cmHandleId) {
+ def getModuleReferencesResponse(cmHandleId) {
def moduleReferences = '{"schemas":[' + getModuleNamesForCmHandle(cmHandleId).collect {
MODULE_REFERENCES_RESPONSE_TEMPLATE.replaceAll("<MODULE_NAME>", it)
}.join(',') + ']}'
return mockResponseWithBody(HttpStatus.OK, moduleReferences)
}
- private getModuleResourcesResponse(cmHandleId) {
+ def getModuleResourcesResponse(cmHandleId) {
def moduleResources = '[' + getModuleNamesForCmHandle(cmHandleId).collect {
MODULE_RESOURCES_RESPONSE_TEMPLATE.replaceAll("<MODULE_NAME>", it)
}.join(',') + ']'
return mockResponseWithBody(HttpStatus.OK, moduleResources)
}
- private getModuleNamesForCmHandle(cmHandleId) {
+ def getModuleNamesForCmHandle(cmHandleId) {
if (!moduleNamesPerCmHandleId.containsKey(cmHandleId)) {
throw new IllegalArgumentException('Mock DMI has no modules configured for ' + cmHandleId)
}
return moduleNamesPerCmHandleId.get(cmHandleId)
}
- private static mockResponse(status) {
+ def static mockResponse(status) {
return new MockResponse().setResponseCode(status.value())
}
- private static mockResponseWithBody(status, responseBody) {
+ def static mockResponseWithBody(status, responseBody) {
return new MockResponse()
.setResponseCode(status.value())
.addHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON)
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/base/PolicyDispatcher.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/base/PolicyDispatcher.groovy
new file mode 100644
index 0000000000..27e7563e61
--- /dev/null
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/base/PolicyDispatcher.groovy
@@ -0,0 +1,74 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2024 Nordix Foundation
+ * ================================================================================
+ * 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.integration.base
+
+
+import okhttp3.mockwebserver.Dispatcher
+import okhttp3.mockwebserver.MockResponse
+import okhttp3.mockwebserver.RecordedRequest
+import org.springframework.http.HttpHeaders
+import org.springframework.http.HttpStatus
+import org.springframework.http.MediaType
+import org.testcontainers.shaded.com.fasterxml.jackson.databind.ObjectMapper
+
+/**
+ * This class simulates responses from the Policy Execution server in NCMP integration tests.
+ */
+class PolicyDispatcher extends Dispatcher {
+
+ def objectMapper = new ObjectMapper()
+ def expectedAuthorizationToken = 'ABC'
+ def allowAll = true; // Prevents legacy test being affected
+
+ @Override
+ MockResponse dispatch(RecordedRequest recordedRequest) {
+
+ if (!allowAll && !recordedRequest.getHeader('Authorization').contains(expectedAuthorizationToken)) {
+ return new MockResponse().setResponseCode(401)
+ }
+
+ if (recordedRequest.path != '/v1/execute') {
+ return new MockResponse().setResponseCode(400)
+ }
+
+ def body = objectMapper.readValue(recordedRequest.getBody().readUtf8(), Map.class)
+ def targetIdentifier = body.get('requests').get(0).get('data').get('targetIdentifier')
+ def responseAsMap = [:]
+ responseAsMap.put('decisionId',1)
+ if (allowAll || targetIdentifier == 'fdn1') {
+ responseAsMap.put('decision','allow')
+ responseAsMap.put('message','')
+ } else {
+ responseAsMap.put('decision','deny')
+ responseAsMap.put('message','I only like fdn1')
+ }
+ def responseAsString = objectMapper.writeValueAsString(responseAsMap)
+
+ return mockResponseWithBody(HttpStatus.OK, responseAsString)
+ }
+
+ static mockResponseWithBody(status, responseBody) {
+ return new MockResponse()
+ .setResponseCode(status.value())
+ .addHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON)
+ .setBody(responseBody)
+ }
+}
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/DataServiceIntegrationSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/DataServiceIntegrationSpec.groovy
index b274324d71..d49931eb7e 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/DataServiceIntegrationSpec.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/DataServiceIntegrationSpec.groovy
@@ -459,17 +459,19 @@ class DataServiceIntegrationSpec extends FunctionalSpecBase {
def 'Get delta between 2 anchors'() {
when: 'attempt to get delta report between anchors'
def result = objectUnderTest.getDeltaByDataspaceAndAnchors(FUNCTIONAL_TEST_DATASPACE_3, BOOKSTORE_ANCHOR_3, BOOKSTORE_ANCHOR_5, '/', OMIT_DESCENDANTS)
+ and: 'report is ordered based on xpath'
+ result = result.toList().sort { it.xpath }
then: 'delta report contains expected number of changes'
result.size() == 3
- and: 'delta report contains UPDATE action with expected xpath'
- assert result[0].getAction() == 'update'
+ and: 'delta report contains REPLACE action with expected xpath'
+ assert result[0].getAction() == 'replace'
assert result[0].getXpath() == '/bookstore'
+ and: 'delta report contains CREATE action with expected xpath'
+ assert result[1].getAction() == 'create'
+ assert result[1].getXpath() == "/bookstore-address[@bookstore-name='Crossword Bookstores']"
and: 'delta report contains REMOVE action with expected xpath'
- assert result[1].getAction() == 'remove'
- assert result[1].getXpath() == "/bookstore-address[@bookstore-name='Easons-1']"
- and: 'delta report contains ADD action with expected xpath'
- assert result[2].getAction() == 'add'
- assert result[2].getXpath() == "/bookstore-address[@bookstore-name='Crossword Bookstores']"
+ assert result[2].getAction() == 'remove'
+ assert result[2].getXpath() == "/bookstore-address[@bookstore-name='Easons-1']"
}
def 'Get delta between 2 anchors returns empty response when #scenario'() {
@@ -513,11 +515,11 @@ class DataServiceIntegrationSpec extends FunctionalSpecBase {
'is empty' | "/bookstore/container-without-leaves"
}
- def 'Get delta between anchors for add action, where target data node #scenario'() {
+ def 'Get delta between anchors for "create" action, where target data node #scenario'() {
when: 'attempt to get delta between leaves of data nodes present in 2 anchors'
def result = objectUnderTest.getDeltaByDataspaceAndAnchors(FUNCTIONAL_TEST_DATASPACE_3, BOOKSTORE_ANCHOR_3, BOOKSTORE_ANCHOR_5, parentNodeXpath, INCLUDE_ALL_DESCENDANTS)
then: 'the expected action is present in delta report'
- result.get(0).getAction() == 'add'
+ result.get(0).getAction() == 'create'
and: 'the expected xapth is present in delta report'
result.get(0).getXpath() == parentNodeXpath
where: 'following data was used'
@@ -531,8 +533,8 @@ class DataServiceIntegrationSpec extends FunctionalSpecBase {
def 'Get delta between anchors when leaves of existing data nodes are updated,: #scenario'() {
when: 'attempt to get delta between leaves of existing data nodes'
def result = objectUnderTest.getDeltaByDataspaceAndAnchors(FUNCTIONAL_TEST_DATASPACE_3, sourceAnchor, targetAnchor, xpath, OMIT_DESCENDANTS)
- then: 'expected action is update'
- assert result[0].getAction() == 'update'
+ then: 'expected action is "replace"'
+ assert result[0].getAction() == 'replace'
and: 'the payload has expected leaf values'
def sourceData = result[0].getSourceData()
def targetData = result[0].getTargetData()
@@ -548,8 +550,8 @@ class DataServiceIntegrationSpec extends FunctionalSpecBase {
def 'Get delta between anchors when child data nodes under existing parent data nodes are updated: #scenario'() {
when: 'attempt to get delta between leaves of existing data nodes'
def result = objectUnderTest.getDeltaByDataspaceAndAnchors(FUNCTIONAL_TEST_DATASPACE_3, sourceAnchor, targetAnchor, xpath, DIRECT_CHILDREN_ONLY)
- then: 'expected action is update'
- assert result[0].getAction() == 'update'
+ then: 'expected action is "replace"'
+ assert result[0].getAction() == 'replace'
and: 'the delta report has expected child node xpaths'
def deltaReportEntities = getDeltaReportEntities(result)
def childNodeXpathsInDeltaReport = deltaReportEntities.get('xpaths')
@@ -571,8 +573,8 @@ class DataServiceIntegrationSpec extends FunctionalSpecBase {
when: 'attempt to get delta between leaves of existing data nodes'
def result = objectUnderTest.getDeltaByDataspaceAndAnchors(FUNCTIONAL_TEST_DATASPACE_3, BOOKSTORE_ANCHOR_3, BOOKSTORE_ANCHOR_5, parentNodeXpath, INCLUDE_ALL_DESCENDANTS)
def deltaReportEntities = getDeltaReportEntities(result)
- then: 'expected action is update'
- assert result[0].getAction() == 'update'
+ then: 'expected action is "replace"'
+ assert result[0].getAction() == 'replace'
and: 'the payload has expected parent node xpath'
assert deltaReportEntities.get('xpaths').contains(parentNodeXpath)
and: 'delta report has expected source and target data'
@@ -591,14 +593,14 @@ class DataServiceIntegrationSpec extends FunctionalSpecBase {
def result = objectUnderTest.getDeltaByDataspaceAnchorAndPayload(FUNCTIONAL_TEST_DATASPACE_3, BOOKSTORE_ANCHOR_3, '/', [:], jsonPayload, OMIT_DESCENDANTS)
then: 'delta report contains expected number of changes'
result.size() == 3
- and: 'delta report contains UPDATE action with expected xpath'
- assert result[0].getAction() == 'update'
+ and: 'delta report contains "replace" action with expected xpath'
+ assert result[0].getAction() == 'replace'
assert result[0].getXpath() == '/bookstore'
- and: 'delta report contains REMOVE action with expected xpath'
+ and: 'delta report contains "remove" action with expected xpath'
assert result[1].getAction() == 'remove'
assert result[1].getXpath() == "/bookstore-address[@bookstore-name='Easons-1']"
- and: 'delta report contains ADD action with expected xpath'
- assert result[2].getAction() == 'add'
+ and: 'delta report contains "create" action with expected xpath'
+ assert result[2].getAction() == 'create'
assert result[2].getXpath() == "/bookstore-address[@bookstore-name='Crossword Bookstores']"
}
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/QueryServiceIntegrationSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/QueryServiceIntegrationSpec.groovy
index 69598a0604..5c2a4fc665 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/QueryServiceIntegrationSpec.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/QueryServiceIntegrationSpec.groovy
@@ -271,7 +271,6 @@ class QueryServiceIntegrationSpec extends FunctionalSpecBase {
'ancestor with parent list' | '//books/ancestor::bookstore/categories' || ["/bookstore/categories[@code='1']", "/bookstore/categories[@code='2']", "/bookstore/categories[@code='3']", "/bookstore/categories[@code='4']", "/bookstore/categories[@code='5']"]
'ancestor with parent list element' | '//books/ancestor::bookstore/categories[@code="2"]' || ["/bookstore/categories[@code='2']"]
'ancestor combined with text condition' | '//books/title[text()="Matilda"]/ancestor::bookstore' || ["/bookstore"]
- 'ancestor same as target type' | '//books/title[text()="Matilda"]/ancestor::books' || ["/bookstore/categories[@code='1']/books[@title='Matilda']"]
}
def 'Cps Path query across anchors with #scenario descendants.'() {
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/AlternateIdSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/AlternateIdSpec.groovy
new file mode 100644
index 0000000000..222b3c0f6f
--- /dev/null
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/AlternateIdSpec.groovy
@@ -0,0 +1,54 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2024 Nordix Foundation
+ * ================================================================================
+ * 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.integration.functional.ncmp
+
+import org.onap.cps.integration.base.CpsIntegrationSpecBase
+import org.springframework.http.HttpStatus
+import org.springframework.http.MediaType
+
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get
+
+class AlternateIdSpec extends CpsIntegrationSpecBase {
+
+ def setup() {
+ dmiDispatcher1.moduleNamesPerCmHandleId['ch-1'] = ['M1', 'M2']
+ registerCmHandle(DMI1_URL, 'ch-1', NO_MODULE_SET_TAG, 'alternateId')
+ }
+
+ def cleanup() {
+ deregisterCmHandle(DMI1_URL, 'ch-1')
+ }
+
+ def 'AlternateId in pass-through data operations should return OK status.'() {
+ given: 'the URL for the pass-through data request'
+ def url = '/ncmp/v1/ch/alternateId/data/ds/ncmp-datastore:passthrough-running'
+ when: 'a pass-through data request is sent to NCMP'
+ def response = mvc.perform(get(url)
+ .queryParam('resourceIdentifier', 'my-resource-id')
+ .contentType(MediaType.APPLICATION_JSON))
+ .andReturn().response
+ then: 'response status is Ok'
+ assert response.status == HttpStatus.OK.value()
+ }
+
+
+
+}
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/CmHandleCreateSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/CmHandleCreateSpec.groovy
index 3d526c6a42..d27badccb2 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/CmHandleCreateSpec.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/CmHandleCreateSpec.groovy
@@ -24,6 +24,7 @@ import org.apache.kafka.common.TopicPartition
import org.apache.kafka.common.serialization.StringDeserializer
import org.onap.cps.integration.KafkaTestContainer
import org.onap.cps.integration.base.CpsIntegrationSpecBase
+import org.onap.cps.ncmp.api.NcmpResponseStatus
import org.onap.cps.ncmp.api.inventory.NetworkCmProxyInventoryFacade
import org.onap.cps.ncmp.api.inventory.models.CmHandleRegistrationResponse
import org.onap.cps.ncmp.api.inventory.models.DmiPluginRegistration
@@ -133,6 +134,38 @@ class CmHandleCreateSpec extends CpsIntegrationSpecBase {
deregisterCmHandles(DMI1_URL, ['ch-1', 'ch-2', 'ch-3'])
}
+ def 'Create CM-handles with alternate IDs.'() {
+ given: 'DMI will return modules for all CM-handles when requested'
+ dmiDispatcher1.moduleNamesPerCmHandleId = (1..7).collectEntries{ ['ch-'+it, ['M1']] }
+ and: 'an existing CM-handle with an alternate ID'
+ registerCmHandle(DMI1_URL, 'ch-1', NO_MODULE_SET_TAG, 'existing-alt-id')
+ and: 'an existing CM-handle with no alternate ID'
+ registerCmHandle(DMI1_URL, 'ch-2', NO_MODULE_SET_TAG, NO_ALTERNATE_ID)
+
+ when: 'a batch of CM-handles is registered for creation with various alternate IDs'
+ def cmHandlesToCreate = [
+ new NcmpServiceCmHandle(cmHandleId: 'ch-3', alternateId: NO_ALTERNATE_ID),
+ new NcmpServiceCmHandle(cmHandleId: 'ch-4', alternateId: 'unique-alt-id'),
+ new NcmpServiceCmHandle(cmHandleId: 'ch-5', alternateId: 'existing-alt-id'),
+ new NcmpServiceCmHandle(cmHandleId: 'ch-6', alternateId: 'duplicate-alt-id'),
+ new NcmpServiceCmHandle(cmHandleId: 'ch-7', alternateId: 'duplicate-alt-id'),
+ ]
+ def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: DMI1_URL, createdCmHandles: cmHandlesToCreate)
+ def dmiPluginRegistrationResponse = objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
+
+ then: 'registration gives expected responses'
+ assert dmiPluginRegistrationResponse.createdCmHandles.sort { it.cmHandle } == [
+ CmHandleRegistrationResponse.createSuccessResponse('ch-3'),
+ CmHandleRegistrationResponse.createSuccessResponse('ch-4'),
+ CmHandleRegistrationResponse.createFailureResponse('ch-5', NcmpResponseStatus.ALTERNATE_ID_ALREADY_ASSOCIATED),
+ CmHandleRegistrationResponse.createSuccessResponse('ch-6'),
+ CmHandleRegistrationResponse.createFailureResponse('ch-7', NcmpResponseStatus.ALTERNATE_ID_ALREADY_ASSOCIATED),
+ ]
+
+ cleanup: 'deregister CM handles'
+ deregisterCmHandles(DMI1_URL, (1..7).collect{ 'ch-'+it })
+ }
+
def 'CM Handle retry after failed module sync.'() {
given: 'DMI is not initially available to handle requests'
dmiDispatcher1.isAvailable = false
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/CmHandleUpdateSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/CmHandleUpdateSpec.groovy
new file mode 100644
index 0000000000..2d1588ecf9
--- /dev/null
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/CmHandleUpdateSpec.groovy
@@ -0,0 +1,89 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2024 Nordix Foundation
+ * ================================================================================
+ * 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.integration.functional.ncmp
+
+import org.onap.cps.integration.base.CpsIntegrationSpecBase
+import org.onap.cps.ncmp.api.NcmpResponseStatus
+import org.onap.cps.ncmp.api.inventory.NetworkCmProxyInventoryFacade
+import org.onap.cps.ncmp.api.inventory.models.CmHandleRegistrationResponse
+import org.onap.cps.ncmp.api.inventory.models.DmiPluginRegistration
+import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle
+
+class CmHandleUpdateSpec extends CpsIntegrationSpecBase {
+
+ NetworkCmProxyInventoryFacade objectUnderTest
+
+ def setup() {
+ objectUnderTest = networkCmProxyInventoryFacade
+ }
+
+ def 'Update of CM-handle with new or unchanged alternate ID succeeds.'() {
+ given: 'DMI will return modules when requested'
+ dmiDispatcher1.moduleNamesPerCmHandleId = ['ch-1': ['M1', 'M2']]
+ and: "existing CM-handle with alternate ID: $oldAlternateId"
+ registerCmHandle(DMI1_URL, 'ch-1', NO_MODULE_SET_TAG, oldAlternateId)
+
+ when: "CM-handle is registered for update with new alternate ID: $newAlternateId"
+ def cmHandleToUpdate = new NcmpServiceCmHandle(cmHandleId: 'ch-1', alternateId: newAlternateId)
+ def dmiPluginRegistrationResponse =
+ objectUnderTest.updateDmiRegistrationAndSyncModule(new DmiPluginRegistration(dmiPlugin: DMI1_URL, updatedCmHandles: [cmHandleToUpdate]))
+
+ then: 'registration gives successful response'
+ assert dmiPluginRegistrationResponse.updatedCmHandles == [CmHandleRegistrationResponse.createSuccessResponse('ch-1')]
+
+ and: 'the CM-handle has expected alternate ID'
+ assert objectUnderTest.getNcmpServiceCmHandle('ch-1').alternateId == expectedAlternateId
+
+ cleanup: 'deregister CM handles'
+ deregisterCmHandle(DMI1_URL, 'ch-1')
+
+ where:
+ oldAlternateId | newAlternateId || expectedAlternateId
+ '' | '' || ''
+ '' | 'new' || 'new'
+ 'old' | 'old' || 'old'
+ 'old' | null || 'old'
+ 'old' | '' || 'old'
+ 'old' | ' ' || 'old'
+ }
+
+ def 'Update of CM-handle with previously set alternate ID fails.'() {
+ given: 'DMI will return modules when requested'
+ dmiDispatcher1.moduleNamesPerCmHandleId = ['ch-1': ['M1', 'M2']]
+ and: 'existing CM-handle with alternate ID'
+ registerCmHandle(DMI1_URL, 'ch-1', NO_MODULE_SET_TAG, 'original')
+
+ when: 'a CM-handle is registered for update with new alternate ID'
+ def cmHandleToUpdate = new NcmpServiceCmHandle(cmHandleId: 'ch-1', alternateId: 'new')
+ def dmiPluginRegistrationResponse =
+ objectUnderTest.updateDmiRegistrationAndSyncModule(new DmiPluginRegistration(dmiPlugin: DMI1_URL, updatedCmHandles: [cmHandleToUpdate]))
+
+ then: 'registration gives failure response, due to alternate ID being already associated'
+ assert dmiPluginRegistrationResponse.updatedCmHandles == [CmHandleRegistrationResponse.createFailureResponse('ch-1', NcmpResponseStatus.ALTERNATE_ID_ALREADY_ASSOCIATED)]
+
+ and: 'the CM-handle still has the old alternate ID'
+ assert objectUnderTest.getNcmpServiceCmHandle('ch-1').alternateId == 'original'
+
+ cleanup: 'deregister CM handles'
+ deregisterCmHandle(DMI1_URL, 'ch-1')
+ }
+
+}
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/DataJobResultServiceSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/DataJobResultServiceSpec.groovy
new file mode 100644
index 0000000000..4d04eeeb81
--- /dev/null
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/DataJobResultServiceSpec.groovy
@@ -0,0 +1,44 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2024 Nordix Foundation
+ * ================================================================================
+ * 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.integration.functional.ncmp
+
+import org.onap.cps.integration.base.CpsIntegrationSpecBase
+import org.onap.cps.ncmp.api.datajobs.DataJobResultService
+import org.springframework.beans.factory.annotation.Autowired
+
+class DataJobResultServiceSpec extends CpsIntegrationSpecBase {
+
+ @Autowired
+ DataJobResultService dataJobResultService;
+
+ def 'Get the status of a data job from DMI.'() {
+ given: 'the required data about the data job'
+ def authorization = 'my authorization header'
+ def dmiServiceName = DMI1_URL
+ def dataProducerId = 'some-data-producer-id'
+ def dataProducerJobId = 'some-data-producer-job-id'
+ def destination = 'some-destination'
+ when: 'the data job status checked'
+ def result = dataJobResultService.getDataJobResult(authorization, dmiServiceName, dataProducerId, dataProducerJobId, destination)
+ then: 'the status is that defined in the mock service.'
+ assert result == '{ "result": "some result"}'
+ }
+}
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/DataJobStatusServiceSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/DataJobStatusServiceSpec.groovy
index fdcad2b47b..6e5c0e40c2 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/DataJobStatusServiceSpec.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/DataJobStatusServiceSpec.groovy
@@ -12,12 +12,11 @@ class DataJobStatusServiceSpec extends CpsIntegrationSpecBase {
def 'Get the status of a data job from DMI.'() {
given: 'the required data about the data job'
def dmiServiceName = DMI1_URL
- def requestId = 'some-request-id'
- def dataProducerJobId = 'some-data-producer-job-id'
def dataProducerId = 'some-data-producer-id'
+ def dataProducerJobId = 'some-data-producer-job-id'
def authorization = 'my authorization header'
when: 'the data job status checked'
- def result = dataJobStatusService.getDataJobStatus(authorization, dmiServiceName, requestId, dataProducerJobId, dataProducerId)
+ def result = dataJobStatusService.getDataJobStatus(authorization, dmiServiceName, dataProducerId, dataProducerJobId)
then: 'the status is that defined in the mock service.'
assert result == 'status details from mock service'
}
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/PolicyExecutorIntegrationSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/PolicyExecutorIntegrationSpec.groovy
new file mode 100644
index 0000000000..99f245ae8c
--- /dev/null
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/PolicyExecutorIntegrationSpec.groovy
@@ -0,0 +1,63 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2024 Nordix Foundation
+ * ================================================================================
+ * 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.integration.functional.ncmp
+
+import org.onap.cps.integration.base.CpsIntegrationSpecBase
+import org.springframework.http.HttpHeaders
+import org.springframework.http.MediaType
+
+import static org.springframework.http.HttpMethod.POST
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.request
+
+class PolicyExecutorIntegrationSpec extends CpsIntegrationSpecBase {
+
+ def setup() {
+ // Enable mocked policy executor logic
+ policyDispatcher.allowAll = false;
+ //minimum setup for 2 cm handles with alternate ids
+ dmiDispatcher1.moduleNamesPerCmHandleId = ['ch-1': [], 'ch-2': []]
+ registerCmHandle(DMI1_URL, 'ch-1', NO_MODULE_SET_TAG, 'fdn1')
+ registerCmHandle(DMI1_URL, 'ch-2', NO_MODULE_SET_TAG, 'fdn2')
+ }
+
+ def cleanup() {
+ deregisterCmHandle(DMI1_URL, 'ch-1')
+ deregisterCmHandle(DMI1_URL, 'ch-2')
+ }
+
+ def 'Policy Executor create request with #scenario.'() {
+ when: 'a pass-through write request is sent to NCMP'
+ def response = mvc.perform(request(POST, "/ncmp/v1/ch/$cmHandle/data/ds/ncmp-datastore:passthrough-running")
+ .queryParam('resourceIdentifier', 'my-resource-id')
+ .contentType(MediaType.APPLICATION_JSON)
+ .content('{ "some-json": "data" }')
+ .header(HttpHeaders.AUTHORIZATION, authorization))
+ .andReturn().response
+ then: 'the expected status code is returned'
+ response.getStatus() == execpectedStatusCode
+ where: 'following parameters are used'
+ scenario | cmHandle | authorization || execpectedStatusCode
+ 'accepted cm handle' | 'ch-1' | 'mock expects "ABC"' || 201
+ 'un-accepted cm handle' | 'ch-2' | 'mock expects "ABC"' || 409
+ 'invalid authorization' | 'ch-1' | 'something else' || 500
+ }
+
+}
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/RestApiSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/RestApiSpec.groovy
index 33973e547b..1e1af556f1 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/RestApiSpec.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/RestApiSpec.groovy
@@ -41,7 +41,7 @@ class RestApiSpec extends CpsIntegrationSpecBase {
'ch-3': ['M1', 'M3']
]
when: 'a POST request is made to register the CM Handles'
- def requestBody = '{"dmiPlugin":"'+DMI1_URL+'","createdCmHandles":[{"cmHandle":"ch-1"},{"cmHandle":"ch-2"},{"cmHandle":"ch-3"}]}'
+ def requestBody = '{"dmiPlugin":"'+DMI1_URL+'","createdCmHandles":[{"cmHandle":"ch-1","alternateId":"alt-1"},{"cmHandle":"ch-2","alternateId":"alt-2"},{"cmHandle":"ch-3","alternateId":"alt-3"}]}'
mvc.perform(post('/ncmpInventory/v1/ch').contentType(MediaType.APPLICATION_JSON).content(requestBody))
.andExpect(status().is2xxSuccessful())
then: 'CM-handles go to READY state'
@@ -76,6 +76,27 @@ class RestApiSpec extends CpsIntegrationSpecBase {
'M3' || ['ch-3']
}
+ def 'Search for CM Handles using Cps Path Query.'() {
+ given: 'a JSON request body containing search parameter'
+ def requestBodyWithSearchCondition = """{
+ "cmHandleQueryParameters": [
+ {
+ "conditionName": "cmHandleWithCpsPath",
+ "conditionParameters": [ {"cpsPath" : "%s"} ]
+ }
+ ]
+ }""".formatted(cpsPath)
+ expect: "a search for cps path ${cpsPath} returns expected CM handles"
+ mvc.perform(post('/ncmp/v1/ch/id-searches').contentType(MediaType.APPLICATION_JSON).content(requestBodyWithSearchCondition))
+ .andExpect(status().is2xxSuccessful())
+ .andExpect(jsonPath('$[*]', containsInAnyOrder(expectedCmHandles.toArray())))
+ .andExpect(jsonPath('$', hasSize(expectedCmHandles.size())));
+ where:
+ scenario | cpsPath || expectedCmHandles
+ 'All Ready CM handles' | "//state[@cm-handle-state='READY']" || ['ch-1', 'ch-2', 'ch-3']
+ 'Having Alternate ID alt-3' | "//cm-handles[@alternate-id='alt-3']" || ['ch-3']
+ }
+
def 'De-register CM handles using REST API.'() {
when: 'a POST request is made to deregister the CM Handle'
def requestBody = '{"dmiPlugin":"'+DMI1_URL+'", "removedCmHandles": ["ch-1", "ch-2", "ch-3"]}'
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/WriteSubJobSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/WriteSubJobSpec.groovy
index b73634f40b..834e1399e3 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/WriteSubJobSpec.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/WriteSubJobSpec.groovy
@@ -52,7 +52,7 @@ class WriteSubJobSpec extends CpsIntegrationSpecBase {
given: 'the required input data for the write job'
def authorization = 'my authorization header'
def dataJobWriteRequest = new DataJobWriteRequest([new WriteOperation('p1', '', '', null), new WriteOperation('p2', '', '', null), new WriteOperation('p3', '', '', null)])
- def myDataJobMetadata = new DataJobMetadata('', '', '')
+ def myDataJobMetadata = new DataJobMetadata('d1', '', '')
def dataJobId = 'my-data-job-id'
when: 'sending a write job to NCMP with 2 sub-jobs for DMI 1 and 1 sub-job for DMI 2'
def response = dataJobService.writeDataJob(authorization, dataJobId, myDataJobMetadata, dataJobWriteRequest)
@@ -63,12 +63,12 @@ class WriteSubJobSpec extends CpsIntegrationSpecBase {
assert response[0].dmiServiceName == "some dmi service name"
assert response[0].dataProducerId == "some data producer id"
and: 'dmi 1 received the correct job details'
- def receivedSubJobsForDispatcher1 = dmiDispatcher1.receivedSubJobs['my-data-job-id']['data'].collect()
+ def receivedSubJobsForDispatcher1 = dmiDispatcher1.receivedSubJobs['?destination=d1']['data'].collect()
assert receivedSubJobsForDispatcher1.size() == 2
assert receivedSubJobsForDispatcher1[0]['path'] == 'p1'
assert receivedSubJobsForDispatcher1[1]['path'] == 'p2'
and: 'dmi 2 received the correct job details'
- def receivedSubJobsForDispatcher2 = dmiDispatcher2.receivedSubJobs['my-data-job-id']['data'].collect()
+ def receivedSubJobsForDispatcher2 = dmiDispatcher2.receivedSubJobs['?destination=d1']['data'].collect()
assert receivedSubJobsForDispatcher2.size() == 1
assert receivedSubJobsForDispatcher2[0]['path'] == 'p3'
}
diff --git a/integration-test/src/test/resources/application.yml b/integration-test/src/test/resources/application.yml
index fefae345e6..760dad01af 100644
--- a/integration-test/src/test/resources/application.yml
+++ b/integration-test/src/test/resources/application.yml
@@ -213,6 +213,20 @@ ncmp:
init:
mode: ALWAYS
+ policy-executor:
+ enabled: true
+ server:
+ address: http://localhost
+ port: 8790
+ httpclient:
+ all-services:
+ maximumInMemorySizeInMegabytes: 1
+ maximumConnectionsTotal: 10
+ pendingAcquireMaxCount: 10
+ connectionTimeoutInSeconds: 30
+ readTimeoutInSeconds: 30
+ writeTimeoutInSeconds: 30
+
hazelcast:
cluster-name: cps-and-ncmp-test-caches
mode: