Add component for deleting resources and tempates
[ccsdk/cds.git] / ms / blueprintsprocessor / functions / resource-resolution / src / test / kotlin / org / onap / ccsdk / cds / blueprintsprocessor / functions / resource / resolution / ResourceDeletionComponentTest.kt
1 /*
2  * Copyright © 2022 Bell Canada
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution
18
19 import com.fasterxml.jackson.databind.JsonNode
20 import com.fasterxml.jackson.databind.node.NullNode
21 import io.mockk.coEvery
22 import io.mockk.every
23 import io.mockk.mockk
24 import io.mockk.slot
25 import io.mockk.spyk
26 import junit.framework.Assert.assertEquals
27 import junit.framework.Assert.assertTrue
28 import kotlinx.coroutines.runBlocking
29 import org.junit.Before
30 import org.junit.Test
31 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput
32 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceDeletionComponent.Companion.ATTRIBUTE_RESULT
33 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceDeletionComponent.Companion.ATTRIBUTE_SUCCESS
34 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceDeletionComponent.Companion.INPUT_FAIL_ON_EMPTY
35 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceDeletionComponent.Companion.INPUT_LAST_N_OCCURRENCES
36 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOLUTION_KEY
37 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_ID
38 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_TYPE
39 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db.ResourceResolutionDBService
40 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db.TemplateResolutionService
41 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
42 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
43 import org.onap.ccsdk.cds.controllerblueprints.core.asJsonNode
44 import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive
45 import org.onap.ccsdk.cds.controllerblueprints.core.asJsonType
46 import org.onap.ccsdk.cds.controllerblueprints.core.data.ServiceTemplate
47 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintContext
48 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintRuntimeService
49 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
50
51 class ResourceDeletionComponentTest {
52
53     private val blueprintName = "testCBA"
54     private val blueprintVersion = "1.0.0"
55     private val artifactNames = listOf("artifact-a", "artifact-b")
56     private val resolutionKey = "resolutionKey"
57     private val resourceId = "1"
58     private val resourceType = "ServiceInstance"
59     private val nodetemplateName = "resource-deletion"
60     private val executionRequest = ExecutionServiceInput()
61
62     private lateinit var resourceResolutionDBService: ResourceResolutionDBService
63     private lateinit var templateResolutionService: TemplateResolutionService
64     private lateinit var resourceDeletionComponent: ResourceDeletionComponent
65     private lateinit var bluePrintRuntimeService: BluePrintRuntimeService<*>
66
67     private val props = mutableMapOf<String, JsonNode>()
68
69     private var success = slot<JsonNode>()
70     private var result = slot<JsonNode>()
71
72     @Before
73     fun setup() {
74         bluePrintRuntimeService = spyk()
75         every { bluePrintRuntimeService.bluePrintContext() }.returns(
76             BluePrintContext(
77                 ServiceTemplate().apply {
78                     this.metadata = mutableMapOf(
79                         BluePrintConstants.METADATA_TEMPLATE_VERSION to blueprintVersion,
80                         BluePrintConstants.METADATA_TEMPLATE_NAME to blueprintName
81                     )
82                 }
83             )
84         )
85         every { bluePrintRuntimeService.setNodeTemplateAttributeValue(nodetemplateName, ATTRIBUTE_SUCCESS, capture(success)) }
86             .answers { }
87         every { bluePrintRuntimeService.setNodeTemplateAttributeValue(nodetemplateName, ATTRIBUTE_RESULT, capture(result)) }
88             .answers { }
89
90         resourceResolutionDBService = mockk()
91         templateResolutionService = mockk()
92         resourceDeletionComponent = ResourceDeletionComponent(resourceResolutionDBService, templateResolutionService)
93         resourceDeletionComponent.bluePrintRuntimeService = bluePrintRuntimeService
94         resourceDeletionComponent.nodeTemplateName = nodetemplateName
95         resourceDeletionComponent.executionServiceInput = executionRequest
96         resourceDeletionComponent.processId = "12"
97         resourceDeletionComponent.workflowName = "workflow"
98         resourceDeletionComponent.stepName = "step"
99         resourceDeletionComponent.interfaceName = "interfaceName"
100         resourceDeletionComponent.operationName = "operationName"
101
102         props[RESOURCE_RESOLUTION_INPUT_RESOLUTION_KEY] = NullNode.getInstance()
103         props[RESOURCE_RESOLUTION_INPUT_RESOURCE_ID] = NullNode.getInstance()
104         props[RESOURCE_RESOLUTION_INPUT_RESOURCE_TYPE] = NullNode.getInstance()
105         props[ResourceResolutionConstants.INPUT_ARTIFACT_PREFIX_NAMES] = artifactNames.asJsonType()
106         props[INPUT_FAIL_ON_EMPTY] = NullNode.getInstance()
107         props[INPUT_LAST_N_OCCURRENCES] = NullNode.getInstance()
108         resourceDeletionComponent.operationInputs = props
109     }
110
111     @Test
112     fun `using resolution-key`() {
113         props[RESOURCE_RESOLUTION_INPUT_RESOLUTION_KEY] = resolutionKey.asJsonPrimitive()
114
115         coEvery {
116             templateResolutionService.deleteTemplates(blueprintName, blueprintVersion, any(), resolutionKey, null)
117         }.returns(1)
118
119         coEvery {
120             resourceResolutionDBService.deleteResources(blueprintName, blueprintVersion, any(), resolutionKey, null)
121         }.returns(2)
122
123         runBlocking { resourceDeletionComponent.processNB(executionRequest) }
124
125         val expected = ResourceDeletionComponent.DeletionResult(1, 2).asJsonType()
126         val result: JsonNode = result.captured
127         assertEquals(expected, result[artifactNames[0]])
128         assertEquals(expected, result[artifactNames[1]])
129         assertEquals(true.asJsonPrimitive(), success.captured)
130     }
131
132     @Test
133     fun `using resource-type and resource-id`() {
134         props[RESOURCE_RESOLUTION_INPUT_RESOURCE_ID] = resourceId.asJsonPrimitive()
135         props[RESOURCE_RESOLUTION_INPUT_RESOURCE_TYPE] = resourceType.asJsonPrimitive()
136
137         coEvery {
138             templateResolutionService.deleteTemplates(blueprintName, blueprintVersion, any(), resourceType, resourceId, null)
139         }.returns(2)
140
141         coEvery {
142             resourceResolutionDBService.deleteResources(blueprintName, blueprintVersion, any(), resourceType, resourceId, null)
143         }.returns(4)
144
145         runBlocking { resourceDeletionComponent.processNB(executionRequest) }
146
147         val expected = ResourceDeletionComponent.DeletionResult(2, 4).asJsonType()
148         val result: JsonNode = result.captured
149         assertEquals(expected, result[artifactNames[0]])
150         assertEquals(expected, result[artifactNames[1]])
151         assertEquals(true.asJsonPrimitive(), success.captured)
152     }
153
154     @Test(expected = BluePrintProcessorException::class)
155     fun `using resource-type missing resource-id`() {
156         props[RESOURCE_RESOLUTION_INPUT_RESOURCE_TYPE] = resourceType.asJsonPrimitive()
157         runBlocking { resourceDeletionComponent.processNB(executionRequest) }
158     }
159
160     @Test(expected = BluePrintProcessorException::class)
161     fun `using resource-id missing resource-type`() {
162         props[RESOURCE_RESOLUTION_INPUT_RESOURCE_ID] = resourceId.asJsonPrimitive()
163         runBlocking { resourceDeletionComponent.processNB(executionRequest) }
164     }
165
166     @Test
167     fun `attributes present when failing`() {
168         val threwException = runBlocking {
169             try {
170                 resourceDeletionComponent.processNB(executionRequest)
171                 false
172             } catch (e: Exception) {
173                 true
174             }
175         }
176         assertTrue(threwException)
177         assertEquals(false.asJsonPrimitive(), success.captured)
178         assertEquals(emptyMap<String, Any>().asJsonNode(), result.captured)
179     }
180
181     @Test
182     fun `last-n-occurrences`() {
183         props[RESOURCE_RESOLUTION_INPUT_RESOLUTION_KEY] = resolutionKey.asJsonPrimitive()
184         props[INPUT_LAST_N_OCCURRENCES] = JacksonUtils.jsonNodeFromObject(3)
185
186         coEvery {
187             templateResolutionService.deleteTemplates(blueprintName, blueprintVersion, any(), resolutionKey, 3)
188         }.returns(3)
189
190         coEvery {
191             resourceResolutionDBService.deleteResources(blueprintName, blueprintVersion, any(), resolutionKey, 3)
192         }.returns(6)
193
194         runBlocking { resourceDeletionComponent.processNB(executionRequest) }
195
196         val expected = ResourceDeletionComponent.DeletionResult(3, 6).asJsonType()
197         val result: JsonNode = result.captured
198         assertEquals(expected, result[artifactNames[0]])
199         assertEquals(expected, result[artifactNames[1]])
200         assertEquals(true.asJsonPrimitive(), success.captured)
201     }
202
203     @Test
204     fun `fail-on-empty nothing deleted`() {
205         props[RESOURCE_RESOLUTION_INPUT_RESOLUTION_KEY] = resolutionKey.asJsonPrimitive()
206         props[INPUT_FAIL_ON_EMPTY] = true.asJsonPrimitive()
207
208         coEvery {
209             templateResolutionService.deleteTemplates(blueprintName, blueprintVersion, any(), resolutionKey, null)
210         }.returns(0)
211
212         coEvery {
213             resourceResolutionDBService.deleteResources(blueprintName, blueprintVersion, any(), resolutionKey, null)
214         }.returns(0)
215
216         val threwException = runBlocking {
217             try {
218                 resourceDeletionComponent.processNB(executionRequest)
219                 false
220             } catch (e: BluePrintProcessorException) {
221                 true
222             }
223         }
224
225         val expected = ResourceDeletionComponent.DeletionResult(0, 0).asJsonType()
226         val result: JsonNode = result.captured
227         assertTrue(threwException)
228         assertEquals(expected, result[artifactNames[0]])
229         assertEquals(expected, result[artifactNames[1]])
230         assertEquals(false.asJsonPrimitive(), success.captured)
231     }
232
233     @Test
234     fun `fail-on-empty something deleted`() {
235         props[RESOURCE_RESOLUTION_INPUT_RESOLUTION_KEY] = resolutionKey.asJsonPrimitive()
236         props[INPUT_FAIL_ON_EMPTY] = true.asJsonPrimitive()
237
238         coEvery {
239             templateResolutionService.deleteTemplates(blueprintName, blueprintVersion, any(), resolutionKey, null)
240         }.returns(1)
241
242         coEvery {
243             resourceResolutionDBService.deleteResources(blueprintName, blueprintVersion, any(), resolutionKey, null)
244         }.returns(1)
245
246         runBlocking { resourceDeletionComponent.processNB(executionRequest) }
247
248         val expected = ResourceDeletionComponent.DeletionResult(1, 1).asJsonType()
249         val result: JsonNode = result.captured
250         assertEquals(expected, result[artifactNames[0]])
251         assertEquals(expected, result[artifactNames[1]])
252         assertEquals(true.asJsonPrimitive(), success.captured)
253     }
254
255     @Test
256     fun `db throws exception`() {
257         props[RESOURCE_RESOLUTION_INPUT_RESOLUTION_KEY] = resolutionKey.asJsonPrimitive()
258
259         coEvery {
260             templateResolutionService.deleteTemplates(blueprintName, blueprintVersion, any(), resolutionKey, null)
261         }.throws(RuntimeException("DB failure!"))
262
263         val threwException = runBlocking {
264             try {
265                 resourceDeletionComponent.processNB(executionRequest)
266                 false
267             } catch (e: Exception) {
268                 true
269             }
270         }
271
272         assertTrue(threwException)
273         assertEquals(false.asJsonPrimitive(), success.captured)
274         assertEquals(emptyMap<String, Any>().asJsonNode(), result.captured)
275     }
276 }