2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2024 Nordix Foundation
4 * ================================================================================
5 * Licensed under the Apache License, Version 2.0 (the 'License');
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an 'AS IS' BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 * SPDX-License-Identifier: Apache-2.0
18 * ============LICENSE_END=========================================================
21 package org.onap.cps.integration.functional
23 import org.onap.cps.integration.base.CpsIntegrationSpecBase
24 import org.onap.cps.ncmp.api.NetworkCmProxyDataService
25 import org.onap.cps.ncmp.api.impl.inventory.CmHandleState
26 import org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory
27 import org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse
28 import org.onap.cps.ncmp.api.models.DmiPluginRegistration
29 import org.onap.cps.ncmp.api.models.UpgradedCmHandles
30 import org.springframework.http.HttpStatus
31 import spock.lang.Ignore
32 import spock.util.concurrent.PollingConditions
34 import static org.springframework.test.web.client.match.MockRestRequestMatchers.anything
35 import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus
38 class NcmpCmHandleUpgradeSpec extends CpsIntegrationSpecBase {
40 NetworkCmProxyDataService objectUnderTest
42 static final INITIAL_MODULE_REFERENCES_RESPONSE = readResourceDataFile('mock-dmi-responses/bookStoreAWithModules_M1_M2_Response.json')
43 static final INITIAL_MODULE_RESOURCES_RESPONSE = readResourceDataFile('mock-dmi-responses/bookStoreAWithModules_M1_M2_ResourcesResponse.json')
44 static final UPDATED_MODULE_REFERENCES_RESPONSE = readResourceDataFile('mock-dmi-responses/bookStoreBWithModules_M1_M3_Response.json')
45 static final UPDATED_MODULE_RESOURCES_RESPONSE = readResourceDataFile('mock-dmi-responses/bookStoreBWithModules_M1_M3_ResourcesResponse.json')
46 static final CM_HANDLE_ID = 'ch-1'
47 static final CM_HANDLE_ID_WITH_EXISTING_MODULE_SET_TAG = 'ch-2'
50 objectUnderTest = networkCmProxyDataService
51 mockDmiWillRespondToHealthChecks(DMI_URL)
54 def 'Upgrade CM-handle with new moduleSetTag or no moduleSetTag.'() {
55 given: 'DMI will return modules for initial registration'
56 mockDmiResponsesForModuleSync(DMI_URL, CM_HANDLE_ID, INITIAL_MODULE_REFERENCES_RESPONSE, INITIAL_MODULE_RESOURCES_RESPONSE)
57 and: 'DMI returns different modules for upgrade'
58 mockDmiResponsesForModuleSync(DMI_URL, CM_HANDLE_ID, UPDATED_MODULE_REFERENCES_RESPONSE, UPDATED_MODULE_RESOURCES_RESPONSE)
60 when: 'a CM-handle is created with expected initial modules: M1 and M2'
61 registerCmHandle(DMI_URL, CM_HANDLE_ID, initialModuleSetTag)
62 assert ['M1', 'M2'] == objectUnderTest.getYangResourcesModuleReferences(CM_HANDLE_ID).moduleName.sort()
63 and: "the CM-handle is upgraded with given moduleSetTag '${updatedModuleSetTag}'"
64 def cmHandlesToUpgrade = new UpgradedCmHandles(cmHandles: [CM_HANDLE_ID], moduleSetTag: updatedModuleSetTag)
65 def dmiPluginRegistrationResponse = networkCmProxyDataService.updateDmiRegistrationAndSyncModule(
66 new DmiPluginRegistration(dmiPlugin: DMI_URL, upgradedCmHandles: cmHandlesToUpgrade))
68 then: 'registration gives successful response'
69 assert dmiPluginRegistrationResponse.upgradedCmHandles == [CmHandleRegistrationResponse.createSuccessResponse(CM_HANDLE_ID)]
71 and: 'CM-handle is in LOCKED state due to MODULE_UPGRADE'
72 def cmHandleCompositeState = objectUnderTest.getCmHandleCompositeState(CM_HANDLE_ID)
73 assert cmHandleCompositeState.cmHandleState == CmHandleState.LOCKED
74 assert cmHandleCompositeState.lockReason.lockReasonCategory == LockReasonCategory.MODULE_UPGRADE
75 assert cmHandleCompositeState.lockReason.details == "Upgrade to ModuleSetTag: ${updatedModuleSetTag}"
77 when: 'module sync runs'
78 moduleSyncWatchdog.resetPreviouslyFailedCmHandles()
79 moduleSyncWatchdog.moduleSyncAdvisedCmHandles()
81 then: 'CM-handle goes to READY state'
82 new PollingConditions().within(3, () -> {
83 assert CmHandleState.READY == objectUnderTest.getCmHandleCompositeState(CM_HANDLE_ID).cmHandleState
86 and: 'the CM-handle has expected moduleSetTag'
87 assert objectUnderTest.getNcmpServiceCmHandle(CM_HANDLE_ID).moduleSetTag == updatedModuleSetTag
89 and: 'CM-handle has expected updated modules: M1 and M3'
90 assert ['M1', 'M3'] == objectUnderTest.getYangResourcesModuleReferences(CM_HANDLE_ID).moduleName.sort()
92 and: 'DMI received expected requests'
93 mockDmiServer.verify()
95 cleanup: 'deregister CM-handle'
96 deregisterCmHandle(DMI_URL, CM_HANDLE_ID)
99 initialModuleSetTag | updatedModuleSetTag
100 NO_MODULE_SET_TAG | NO_MODULE_SET_TAG
101 NO_MODULE_SET_TAG | 'new'
102 'initial' | NO_MODULE_SET_TAG
106 def 'Upgrade CM-handle with existing moduleSetTag.'() {
107 given: 'DMI will return modules for registration'
108 mockDmiResponsesForModuleSync(DMI_URL, CM_HANDLE_ID, INITIAL_MODULE_REFERENCES_RESPONSE, INITIAL_MODULE_RESOURCES_RESPONSE)
109 mockDmiResponsesForModuleSync(DMI_URL, CM_HANDLE_ID_WITH_EXISTING_MODULE_SET_TAG, UPDATED_MODULE_REFERENCES_RESPONSE, UPDATED_MODULE_RESOURCES_RESPONSE)
110 and: "an existing CM-handle handle with moduleSetTag '${updatedModuleSetTag}'"
111 registerCmHandle(DMI_URL, CM_HANDLE_ID_WITH_EXISTING_MODULE_SET_TAG, updatedModuleSetTag)
112 assert ['M1', 'M3'] == objectUnderTest.getYangResourcesModuleReferences(CM_HANDLE_ID_WITH_EXISTING_MODULE_SET_TAG).moduleName.sort()
113 and: "a CM-handle with moduleSetTag '${initialModuleSetTag}' which will be upgraded"
114 registerCmHandle(DMI_URL, CM_HANDLE_ID, initialModuleSetTag)
115 assert ['M1', 'M2'] == objectUnderTest.getYangResourcesModuleReferences(CM_HANDLE_ID).moduleName.sort()
117 when: "CM-handle is upgraded to moduleSetTag '${updatedModuleSetTag}'"
118 def cmHandlesToUpgrade = new UpgradedCmHandles(cmHandles: [CM_HANDLE_ID], moduleSetTag: updatedModuleSetTag)
119 def dmiPluginRegistrationResponse = networkCmProxyDataService.updateDmiRegistrationAndSyncModule(
120 new DmiPluginRegistration(dmiPlugin: DMI_URL, upgradedCmHandles: cmHandlesToUpgrade))
122 then: 'registration gives successful response'
123 assert dmiPluginRegistrationResponse.upgradedCmHandles == [CmHandleRegistrationResponse.createSuccessResponse(CM_HANDLE_ID)]
125 when: 'module sync runs'
126 moduleSyncWatchdog.resetPreviouslyFailedCmHandles()
127 moduleSyncWatchdog.moduleSyncAdvisedCmHandles()
129 then: 'CM-handle goes to READY state'
130 new PollingConditions().within(3, () -> {
131 assert CmHandleState.READY == objectUnderTest.getCmHandleCompositeState(CM_HANDLE_ID).cmHandleState
134 and: 'the CM-handle has expected moduleSetTag'
135 assert objectUnderTest.getNcmpServiceCmHandle(CM_HANDLE_ID).moduleSetTag == updatedModuleSetTag
137 and: 'CM-handle has expected updated modules: M1 and M3'
138 assert ['M1', 'M3'] == objectUnderTest.getYangResourcesModuleReferences(CM_HANDLE_ID).moduleName.sort()
140 cleanup: 'deregister CM-handle'
141 deregisterCmHandles(DMI_URL, [CM_HANDLE_ID, CM_HANDLE_ID_WITH_EXISTING_MODULE_SET_TAG])
144 initialModuleSetTag | updatedModuleSetTag
145 NO_MODULE_SET_TAG | 'moduleSet2'
146 'moduleSet1' | 'moduleSet2'
149 def 'Skip upgrade of CM-handle with same moduleSetTag as before.'() {
150 given: 'an existing CM-handle with expected initial modules: M1 and M2'
151 mockDmiResponsesForModuleSync(DMI_URL, CM_HANDLE_ID, INITIAL_MODULE_REFERENCES_RESPONSE, INITIAL_MODULE_RESOURCES_RESPONSE)
152 registerCmHandle(DMI_URL, CM_HANDLE_ID, 'same')
153 assert ['M1', 'M2'] == objectUnderTest.getYangResourcesModuleReferences(CM_HANDLE_ID).moduleName.sort()
155 when: 'CM-handle is upgraded with the same moduleSetTag'
156 def cmHandlesToUpgrade = new UpgradedCmHandles(cmHandles: [CM_HANDLE_ID], moduleSetTag: 'same')
157 networkCmProxyDataService.updateDmiRegistrationAndSyncModule(
158 new DmiPluginRegistration(dmiPlugin: DMI_URL, upgradedCmHandles: cmHandlesToUpgrade))
160 then: 'CM-handle remains in READY state'
161 assert CmHandleState.READY == objectUnderTest.getCmHandleCompositeState(CM_HANDLE_ID).cmHandleState
163 and: 'the CM-handle has same moduleSetTag as before'
164 assert objectUnderTest.getNcmpServiceCmHandle(CM_HANDLE_ID).moduleSetTag == 'same'
166 then: 'CM-handle has same modules as before: M1 and M2'
167 assert ['M1', 'M2'] == objectUnderTest.getYangResourcesModuleReferences(CM_HANDLE_ID).moduleName.sort()
169 cleanup: 'deregister CM-handle'
170 deregisterCmHandle(DMI_URL, CM_HANDLE_ID)
173 def 'Upgrade of CM-handle fails due to DMI error.'() {
174 given: 'DMI will return modules for initial registration'
175 mockDmiResponsesForModuleSync(DMI_URL, CM_HANDLE_ID, INITIAL_MODULE_REFERENCES_RESPONSE, INITIAL_MODULE_RESOURCES_RESPONSE)
176 and: 'DMI returns error code for upgrade'
177 mockDmiServer.expect(anything()).andRespond(withStatus(HttpStatus.SERVICE_UNAVAILABLE))
179 when: 'a CM-handle is created'
180 registerCmHandle(DMI_URL, CM_HANDLE_ID, 'oldTag')
181 and: 'the CM-handle is upgraded'
182 def cmHandlesToUpgrade = new UpgradedCmHandles(cmHandles: [CM_HANDLE_ID], moduleSetTag: 'newTag')
183 networkCmProxyDataService.updateDmiRegistrationAndSyncModule(
184 new DmiPluginRegistration(dmiPlugin: DMI_URL, upgradedCmHandles: cmHandlesToUpgrade))
186 and: 'module sync runs'
187 moduleSyncWatchdog.resetPreviouslyFailedCmHandles()
188 moduleSyncWatchdog.moduleSyncAdvisedCmHandles()
190 then: 'CM-handle goes to LOCKED state with reason MODULE_UPGRADE_FAILED'
191 new PollingConditions().within(3, () -> {
192 def cmHandleCompositeState = objectUnderTest.getCmHandleCompositeState(CM_HANDLE_ID)
193 assert cmHandleCompositeState.cmHandleState == CmHandleState.LOCKED
194 assert cmHandleCompositeState.lockReason.lockReasonCategory == LockReasonCategory.MODULE_UPGRADE_FAILED
197 and: 'the CM-handle has same moduleSetTag as before'
198 assert objectUnderTest.getNcmpServiceCmHandle(CM_HANDLE_ID).moduleSetTag == 'oldTag'
200 cleanup: 'deregister CM-handle'
201 deregisterCmHandle(DMI_URL, CM_HANDLE_ID)