NcmpCloudEventBuilder refactoring
[cps.git] / integration-test / src / test / groovy / org / onap / cps / integration / functional / NcmpCmHandleUpgradeSpec.groovy
1 /*
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
8  *
9  *        http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  *
17  *  SPDX-License-Identifier: Apache-2.0
18  *  ============LICENSE_END=========================================================
19  */
20
21 package org.onap.cps.integration.functional
22
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.util.concurrent.PollingConditions
32
33 import static org.springframework.test.web.client.match.MockRestRequestMatchers.anything
34 import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus
35
36 class NcmpCmHandleUpgradeSpec extends CpsIntegrationSpecBase {
37
38     NetworkCmProxyDataService objectUnderTest
39
40     static final INITIAL_MODULE_REFERENCES_RESPONSE = readResourceDataFile('mock-dmi-responses/bookStoreAWithModules_M1_M2_Response.json')
41     static final INITIAL_MODULE_RESOURCES_RESPONSE = readResourceDataFile('mock-dmi-responses/bookStoreAWithModules_M1_M2_ResourcesResponse.json')
42     static final UPDATED_MODULE_REFERENCES_RESPONSE = readResourceDataFile('mock-dmi-responses/bookStoreBWithModules_M1_M3_Response.json')
43     static final UPDATED_MODULE_RESOURCES_RESPONSE = readResourceDataFile('mock-dmi-responses/bookStoreBWithModules_M1_M3_ResourcesResponse.json')
44     static final CM_HANDLE_ID = 'ch-1'
45     static final CM_HANDLE_ID_WITH_EXISTING_MODULE_SET_TAG = 'ch-2'
46
47     def setup() {
48         objectUnderTest = networkCmProxyDataService
49         mockDmiWillRespondToHealthChecks(DMI_URL)
50     }
51
52     def 'Upgrade CM-handle with new moduleSetTag or no moduleSetTag.'() {
53         given: 'DMI will return modules for initial registration'
54             mockDmiResponsesForModuleSync(DMI_URL, CM_HANDLE_ID, INITIAL_MODULE_REFERENCES_RESPONSE, INITIAL_MODULE_RESOURCES_RESPONSE)
55         and: 'DMI returns different modules for upgrade'
56             mockDmiResponsesForModuleSync(DMI_URL, CM_HANDLE_ID, UPDATED_MODULE_REFERENCES_RESPONSE, UPDATED_MODULE_RESOURCES_RESPONSE)
57
58         when: 'a CM-handle is created with expected initial modules: M1 and M2'
59             registerCmHandle(DMI_URL, CM_HANDLE_ID, initialModuleSetTag)
60             assert ['M1', 'M2'] == objectUnderTest.getYangResourcesModuleReferences(CM_HANDLE_ID).moduleName.sort()
61         and: "the CM-handle is upgraded with given moduleSetTag '${updatedModuleSetTag}'"
62             def cmHandlesToUpgrade = new UpgradedCmHandles(cmHandles: [CM_HANDLE_ID], moduleSetTag: updatedModuleSetTag)
63             def dmiPluginRegistrationResponse = networkCmProxyDataService.updateDmiRegistrationAndSyncModule(
64                     new DmiPluginRegistration(dmiPlugin: DMI_URL, upgradedCmHandles: cmHandlesToUpgrade))
65
66         then: 'registration gives successful response'
67             assert dmiPluginRegistrationResponse.upgradedCmHandles == [CmHandleRegistrationResponse.createSuccessResponse(CM_HANDLE_ID)]
68
69         and: 'CM-handle is in LOCKED state due to MODULE_UPGRADE'
70             def cmHandleCompositeState = objectUnderTest.getCmHandleCompositeState(CM_HANDLE_ID)
71             assert cmHandleCompositeState.cmHandleState == CmHandleState.LOCKED
72             assert cmHandleCompositeState.lockReason.lockReasonCategory == LockReasonCategory.MODULE_UPGRADE
73             assert cmHandleCompositeState.lockReason.details == "Upgrade to ModuleSetTag: ${updatedModuleSetTag}"
74
75         when: 'module sync runs'
76             moduleSyncWatchdog.resetPreviouslyFailedCmHandles()
77             moduleSyncWatchdog.moduleSyncAdvisedCmHandles()
78
79         then: 'CM-handle goes to READY state'
80             new PollingConditions().within(3, () -> {
81                 assert CmHandleState.READY == objectUnderTest.getCmHandleCompositeState(CM_HANDLE_ID).cmHandleState
82             })
83
84         and: 'the CM-handle has expected moduleSetTag'
85             assert objectUnderTest.getNcmpServiceCmHandle(CM_HANDLE_ID).moduleSetTag == updatedModuleSetTag
86
87         and: 'CM-handle has expected updated modules: M1 and M3'
88             assert ['M1', 'M3'] == objectUnderTest.getYangResourcesModuleReferences(CM_HANDLE_ID).moduleName.sort()
89
90         and: 'DMI received expected requests'
91             mockDmiServer.verify()
92
93         cleanup: 'deregister CM-handle'
94             deregisterCmHandle(DMI_URL, CM_HANDLE_ID)
95
96         where:
97             initialModuleSetTag | updatedModuleSetTag
98             NO_MODULE_SET_TAG   | NO_MODULE_SET_TAG
99             NO_MODULE_SET_TAG   | 'new'
100             'initial'           | NO_MODULE_SET_TAG
101             'initial'           | 'new'
102     }
103
104     def 'Upgrade CM-handle with existing moduleSetTag.'() {
105         given: 'DMI will return modules for registration'
106             mockDmiResponsesForModuleSync(DMI_URL, CM_HANDLE_ID, INITIAL_MODULE_REFERENCES_RESPONSE, INITIAL_MODULE_RESOURCES_RESPONSE)
107             mockDmiResponsesForModuleSync(DMI_URL, CM_HANDLE_ID_WITH_EXISTING_MODULE_SET_TAG, UPDATED_MODULE_REFERENCES_RESPONSE, UPDATED_MODULE_RESOURCES_RESPONSE)
108         and: "an existing CM-handle handle with moduleSetTag '${updatedModuleSetTag}'"
109             registerCmHandle(DMI_URL, CM_HANDLE_ID_WITH_EXISTING_MODULE_SET_TAG, updatedModuleSetTag)
110             assert ['M1', 'M3'] == objectUnderTest.getYangResourcesModuleReferences(CM_HANDLE_ID_WITH_EXISTING_MODULE_SET_TAG).moduleName.sort()
111         and: "a CM-handle with moduleSetTag '${initialModuleSetTag}' which will be upgraded"
112             registerCmHandle(DMI_URL, CM_HANDLE_ID, initialModuleSetTag)
113             assert ['M1', 'M2'] == objectUnderTest.getYangResourcesModuleReferences(CM_HANDLE_ID).moduleName.sort()
114
115         when: "CM-handle is upgraded to moduleSetTag '${updatedModuleSetTag}'"
116             def cmHandlesToUpgrade = new UpgradedCmHandles(cmHandles: [CM_HANDLE_ID], moduleSetTag: updatedModuleSetTag)
117             def dmiPluginRegistrationResponse = networkCmProxyDataService.updateDmiRegistrationAndSyncModule(
118                     new DmiPluginRegistration(dmiPlugin: DMI_URL, upgradedCmHandles: cmHandlesToUpgrade))
119
120         then: 'registration gives successful response'
121             assert dmiPluginRegistrationResponse.upgradedCmHandles == [CmHandleRegistrationResponse.createSuccessResponse(CM_HANDLE_ID)]
122
123         when: 'module sync runs'
124             moduleSyncWatchdog.resetPreviouslyFailedCmHandles()
125             moduleSyncWatchdog.moduleSyncAdvisedCmHandles()
126
127         then: 'CM-handle goes to READY state'
128             new PollingConditions().within(3, () -> {
129                 assert CmHandleState.READY == objectUnderTest.getCmHandleCompositeState(CM_HANDLE_ID).cmHandleState
130             })
131
132         and: 'the CM-handle has expected moduleSetTag'
133             assert objectUnderTest.getNcmpServiceCmHandle(CM_HANDLE_ID).moduleSetTag == updatedModuleSetTag
134
135         and: 'CM-handle has expected updated modules: M1 and M3'
136             assert ['M1', 'M3'] == objectUnderTest.getYangResourcesModuleReferences(CM_HANDLE_ID).moduleName.sort()
137
138         cleanup: 'deregister CM-handle'
139             deregisterCmHandles(DMI_URL, [CM_HANDLE_ID, CM_HANDLE_ID_WITH_EXISTING_MODULE_SET_TAG])
140
141         where:
142             initialModuleSetTag | updatedModuleSetTag
143             NO_MODULE_SET_TAG   | 'moduleSet2'
144             'moduleSet1'        | 'moduleSet2'
145     }
146
147     def 'Skip upgrade of CM-handle with same moduleSetTag as before.'() {
148         given: 'an existing CM-handle with expected initial modules: M1 and M2'
149             mockDmiResponsesForModuleSync(DMI_URL, CM_HANDLE_ID, INITIAL_MODULE_REFERENCES_RESPONSE, INITIAL_MODULE_RESOURCES_RESPONSE)
150             registerCmHandle(DMI_URL, CM_HANDLE_ID, 'same')
151             assert ['M1', 'M2'] == objectUnderTest.getYangResourcesModuleReferences(CM_HANDLE_ID).moduleName.sort()
152
153         when: 'CM-handle is upgraded with the same moduleSetTag'
154             def cmHandlesToUpgrade = new UpgradedCmHandles(cmHandles: [CM_HANDLE_ID], moduleSetTag: 'same')
155             networkCmProxyDataService.updateDmiRegistrationAndSyncModule(
156                     new DmiPluginRegistration(dmiPlugin: DMI_URL, upgradedCmHandles: cmHandlesToUpgrade))
157
158         then: 'CM-handle remains in READY state'
159             assert CmHandleState.READY == objectUnderTest.getCmHandleCompositeState(CM_HANDLE_ID).cmHandleState
160
161         and: 'the CM-handle has same moduleSetTag as before'
162             assert objectUnderTest.getNcmpServiceCmHandle(CM_HANDLE_ID).moduleSetTag == 'same'
163
164         then: 'CM-handle has same modules as before: M1 and M2'
165             assert ['M1', 'M2'] == objectUnderTest.getYangResourcesModuleReferences(CM_HANDLE_ID).moduleName.sort()
166
167         cleanup: 'deregister CM-handle'
168             deregisterCmHandle(DMI_URL, CM_HANDLE_ID)
169     }
170
171     def 'Upgrade of CM-handle fails due to DMI error.'() {
172         given: 'DMI will return modules for initial registration'
173             mockDmiResponsesForModuleSync(DMI_URL, CM_HANDLE_ID, INITIAL_MODULE_REFERENCES_RESPONSE, INITIAL_MODULE_RESOURCES_RESPONSE)
174         and: 'DMI returns error code for upgrade'
175             mockDmiServer.expect(anything()).andRespond(withStatus(HttpStatus.SERVICE_UNAVAILABLE))
176
177         when: 'a CM-handle is created'
178             registerCmHandle(DMI_URL, CM_HANDLE_ID, 'oldTag')
179         and: 'the CM-handle is upgraded'
180             def cmHandlesToUpgrade = new UpgradedCmHandles(cmHandles: [CM_HANDLE_ID], moduleSetTag: 'newTag')
181             networkCmProxyDataService.updateDmiRegistrationAndSyncModule(
182                     new DmiPluginRegistration(dmiPlugin: DMI_URL, upgradedCmHandles: cmHandlesToUpgrade))
183
184         and: 'module sync runs'
185             moduleSyncWatchdog.resetPreviouslyFailedCmHandles()
186             moduleSyncWatchdog.moduleSyncAdvisedCmHandles()
187
188         then: 'CM-handle goes to LOCKED state with reason MODULE_UPGRADE_FAILED'
189             new PollingConditions().within(3, () -> {
190                 def cmHandleCompositeState = objectUnderTest.getCmHandleCompositeState(CM_HANDLE_ID)
191                 assert cmHandleCompositeState.cmHandleState == CmHandleState.LOCKED
192                 assert cmHandleCompositeState.lockReason.lockReasonCategory == LockReasonCategory.MODULE_UPGRADE_FAILED
193             })
194
195         and: 'the CM-handle has same moduleSetTag as before'
196             assert objectUnderTest.getNcmpServiceCmHandle(CM_HANDLE_ID).moduleSetTag == 'oldTag'
197
198         cleanup: 'deregister CM-handle'
199             deregisterCmHandle(DMI_URL, CM_HANDLE_ID)
200     }
201
202 }