Metadata for name, version, tags and type
[ccsdk/cds.git] / ms / blueprintsprocessor / functions / config-snapshots / src / test / kotlin / org / onap / ccsdk / cds / blueprintsprocessor / functions / config / snapshots / ComponentConfigSnapshotsExecutorTest.kt
1 /*
2  *  Copyright © 2019 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.config.snapshots
18
19 import com.fasterxml.jackson.databind.JsonNode
20 import kotlinx.coroutines.runBlocking
21 import org.junit.Assert.assertEquals
22 import org.junit.Assert.assertTrue
23 import org.junit.Before
24 import org.junit.Test
25 import org.junit.runner.RunWith
26 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput
27 import org.onap.ccsdk.cds.blueprintsprocessor.functions.config.snapshots.ComponentConfigSnapshotsExecutor.Companion.DIFF_JSON
28 import org.onap.ccsdk.cds.blueprintsprocessor.functions.config.snapshots.ComponentConfigSnapshotsExecutor.Companion.DIFF_XML
29 import org.onap.ccsdk.cds.blueprintsprocessor.functions.config.snapshots.ComponentConfigSnapshotsExecutor.Companion.OPERATION_DIFF
30 import org.onap.ccsdk.cds.blueprintsprocessor.functions.config.snapshots.ComponentConfigSnapshotsExecutor.Companion.OPERATION_FETCH
31 import org.onap.ccsdk.cds.blueprintsprocessor.functions.config.snapshots.ComponentConfigSnapshotsExecutor.Companion.OPERATION_STORE
32 import org.onap.ccsdk.cds.blueprintsprocessor.functions.config.snapshots.db.ResourceConfigSnapshot
33 import org.onap.ccsdk.cds.blueprintsprocessor.functions.config.snapshots.db.ResourceConfigSnapshotService
34 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
35 import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive
36 import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintMetadataUtils
37 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
38 import org.springframework.beans.factory.annotation.Autowired
39 import org.springframework.context.annotation.ComponentScan
40 import org.springframework.test.context.ContextConfiguration
41 import org.springframework.test.context.TestPropertySource
42 import org.springframework.test.context.junit4.SpringRunner
43
44 @RunWith(SpringRunner::class)
45 @ContextConfiguration(
46     classes = [ResourceConfigSnapshotService::class, TestDatabaseConfiguration::class]
47 )
48 @TestPropertySource(locations = ["classpath:application-test.properties"])
49 @ComponentScan(
50     basePackages = ["org.onap.ccsdk.cds.blueprintsprocessor.functions.config.snapshots"]
51 )
52 @Suppress("SameParameterValue")
53 class ComponentConfigSnapshotsExecutorTest {
54
55     @Autowired
56     lateinit var cfgSnapshotService: ResourceConfigSnapshotService
57     lateinit var cfgSnapshotComponent: ComponentConfigSnapshotsExecutor
58     private var bluePrintRuntimeService = BluePrintMetadataUtils.bluePrintRuntime(
59         "123456-1000",
60         "./../../../../components/model-catalog/blueprint-model/test-blueprint/remote_scripts"
61     )
62
63     private val resourceId = "1"
64     private val resourceType = "ServiceInstance"
65     private val props = mutableMapOf<String, JsonNode>()
66     private val nodeTemplateName = "nodeTemplateName"
67
68     private val executionRequest = ExecutionServiceInput()
69
70     @Before
71     fun setup() {
72         cfgSnapshotComponent = ComponentConfigSnapshotsExecutor(cfgSnapshotService)
73         props[ComponentConfigSnapshotsExecutor.INPUT_RESOURCE_ID] = resourceId.asJsonPrimitive()
74         props[ComponentConfigSnapshotsExecutor.INPUT_RESOURCE_TYPE] = resourceType.asJsonPrimitive()
75
76         cfgSnapshotComponent.operationInputs = props
77         cfgSnapshotComponent.bluePrintRuntimeService = bluePrintRuntimeService
78         cfgSnapshotComponent.nodeTemplateName = nodeTemplateName
79
80         cfgSnapshotComponent.executionServiceInput = executionRequest
81         cfgSnapshotComponent.processId = "12"
82         cfgSnapshotComponent.workflowName = "workflow"
83         cfgSnapshotComponent.stepName = "step"
84         cfgSnapshotComponent.interfaceName = "interfaceName"
85         cfgSnapshotComponent.operationName = "operationName"
86     }
87
88     @Test
89     fun processNBFetchWithResourceIdAndResourceTypeSingleFind() {
90         val snapshot = ResourceConfigSnapshot()
91         val snapshotConfig = "TEST1"
92         snapshot.config_snapshot = snapshotConfig
93
94         runBlocking {
95             try {
96                 val resId = "121111"
97                 val resType = "PNF"
98                 cfgSnapshotService.write(snapshotConfig, resId, resType)
99                 prepareRequestProperties(OPERATION_FETCH, resId, resType, ResourceConfigSnapshot.Status.RUNNING.name)
100
101                 cfgSnapshotComponent.processNB(executionRequest)
102             } catch (e: BluePrintProcessorException) {
103                 kotlin.test.assertEquals(
104                     "Can't proceed with the cfg snapshot lookup: provide resource-id and resource-type.",
105                     e.message
106                 )
107                 return@runBlocking
108             }
109             // then; we should get success and the TEST1 payload in our output properties
110             assertEquals(
111                 ComponentConfigSnapshotsExecutor.OUTPUT_STATUS_SUCCESS.asJsonPrimitive(),
112                 bluePrintRuntimeService.getNodeTemplateAttributeValue(
113                     nodeTemplateName,
114                     ComponentConfigSnapshotsExecutor.OUTPUT_STATUS
115                 )
116             )
117             assertEquals(
118                 snapshotConfig.asJsonPrimitive(),
119                 bluePrintRuntimeService.getNodeTemplateAttributeValue(
120                     nodeTemplateName,
121                     ComponentConfigSnapshotsExecutor.OUTPUT_SNAPSHOT
122                 )
123             )
124         }
125     }
126
127     @Test
128     fun processNBFetchCandidateWithResourceIdAndResourceTypeSingleFind() {
129         val snapshot = ResourceConfigSnapshot()
130         val snapshotConfig = "TEST"
131         snapshot.config_snapshot = snapshotConfig
132
133         runBlocking {
134             try {
135                 val resId = "121111"
136                 val resType = "PNF"
137                 cfgSnapshotService.write(snapshotConfig, resId, resType, ResourceConfigSnapshot.Status.CANDIDATE)
138                 prepareRequestProperties(OPERATION_FETCH, resId, resType, ResourceConfigSnapshot.Status.CANDIDATE.name)
139
140                 cfgSnapshotComponent.processNB(executionRequest)
141             } catch (e: BluePrintProcessorException) {
142                 kotlin.test.assertEquals(
143                     "Can't proceed with the cfg snapshot lookup: provide resource-id and resource-type.",
144                     e.message
145                 )
146                 return@runBlocking
147             }
148             // then; we should get success and the TEST payload in our output properties
149             assertEquals(
150                 ComponentConfigSnapshotsExecutor.OUTPUT_STATUS_SUCCESS.asJsonPrimitive(),
151                 bluePrintRuntimeService.getNodeTemplateAttributeValue(
152                     nodeTemplateName,
153                     ComponentConfigSnapshotsExecutor.OUTPUT_STATUS
154                 )
155             )
156             assertEquals(
157                 snapshotConfig.asJsonPrimitive(),
158                 bluePrintRuntimeService.getNodeTemplateAttributeValue(
159                     nodeTemplateName,
160                     ComponentConfigSnapshotsExecutor.OUTPUT_SNAPSHOT
161                 )
162             )
163         }
164     }
165
166     @Test
167     fun processNBStoreWithResourceIdAndResourceType() {
168         val snapshot = ResourceConfigSnapshot()
169         val snapshotConfig = "PAYLOAD"
170         snapshot.config_snapshot = snapshotConfig
171
172         runBlocking {
173             try {
174                 val resId = "121111"
175                 val resType = "PNF"
176                 prepareRequestProperties(OPERATION_STORE, resId, resType, snapshotConfig)
177
178                 cfgSnapshotComponent.processNB(executionRequest)
179             } catch (e: BluePrintProcessorException) {
180                 kotlin.test.assertEquals(
181                     "Can't proceed with the cfg snapshot lookup: provide resource-id and resource-type.",
182                     e.message
183                 )
184                 return@runBlocking
185             }
186
187             // then; we should get success and the PAYLOAD payload in our output properties
188             assertEquals(
189                 ComponentConfigSnapshotsExecutor.OUTPUT_STATUS_SUCCESS.asJsonPrimitive(),
190                 bluePrintRuntimeService.getNodeTemplateAttributeValue(
191                     nodeTemplateName,
192                     ComponentConfigSnapshotsExecutor.OUTPUT_STATUS
193                 )
194             )
195             assertEquals(
196                 snapshotConfig.asJsonPrimitive(),
197                 bluePrintRuntimeService.getNodeTemplateAttributeValue(
198                     nodeTemplateName,
199                     ComponentConfigSnapshotsExecutor.OUTPUT_SNAPSHOT
200                 )
201             )
202         }
203     }
204
205     @Test
206     fun processNBFetchNoneFound() {
207
208         runBlocking {
209             // when; asking for unknown resource Id/ resource Type combo; should get an error response
210             try {
211                 prepareRequestProperties(OPERATION_FETCH, "asdasd", "PNF", ResourceConfigSnapshot.Status.RUNNING.name)
212
213                 cfgSnapshotComponent.processNB(executionRequest)
214             } catch (e: BluePrintProcessorException) {
215                 kotlin.test.assertEquals(
216                     "Can't proceed with the cfg snapshot lookup: provide resource-id and resource-type.",
217                     e.message
218                 )
219                 return@runBlocking
220             }
221
222             assertEquals(
223                 ComponentConfigSnapshotsExecutor.OUTPUT_STATUS_SUCCESS.asJsonPrimitive(),
224                 bluePrintRuntimeService.getNodeTemplateAttributeValue(
225                     nodeTemplateName,
226                     ComponentConfigSnapshotsExecutor.OUTPUT_STATUS
227                 )
228             )
229         }
230     }
231
232     @Test
233     fun processNBErrorOperationUnknown() {
234
235         runBlocking {
236             // when; asking for unknown operation update; should get an error response
237             try {
238                 prepareRequestProperties("update", "asdasd", "PNF", ResourceConfigSnapshot.Status.RUNNING.name)
239
240                 cfgSnapshotComponent.processNB(executionRequest)
241             } catch (e: BluePrintProcessorException) {
242                 kotlin.test.assertEquals(
243                     "Can't proceed with the cfg snapshot lookup: provide resource-id and resource-type.",
244                     e.message
245                 )
246                 return@runBlocking
247             }
248
249             // then; we should get error in our output properties
250             assertTrue(bluePrintRuntimeService.getBluePrintError().errors.size == 1)
251             assertEquals(
252                 ComponentConfigSnapshotsExecutor.OUTPUT_STATUS_ERROR.asJsonPrimitive(),
253                 bluePrintRuntimeService.getNodeTemplateAttributeValue(
254                     nodeTemplateName,
255                     ComponentConfigSnapshotsExecutor.OUTPUT_STATUS
256                 )
257             )
258             val msg = "Operation parameter must be fetch, store or diff"
259             assertEquals(
260                 msg.asJsonPrimitive(),
261                 bluePrintRuntimeService.getNodeTemplateAttributeValue(
262                     nodeTemplateName,
263                     ComponentConfigSnapshotsExecutor.OUTPUT_MESSAGE
264                 )
265             )
266         }
267     }
268
269     @Test
270     fun processNBErrorDiffContentTypeUnknown() {
271
272         runBlocking {
273             // when; asking for unknown content type diff operation; should get an error response
274             try {
275                 val resId = "121111"
276                 val resType = "PNF"
277                 cfgSnapshotService.write("snapshotConfig", resId, resType, ResourceConfigSnapshot.Status.CANDIDATE)
278                 prepareRequestProperties(OPERATION_DIFF, resId, resType, "YANG")
279
280                 cfgSnapshotComponent.processNB(executionRequest)
281             } catch (e: BluePrintProcessorException) {
282                 kotlin.test.assertEquals(
283                     "Can't proceed with the cfg snapshot lookup: provide resource-id and resource-type.",
284                     e.message
285                 )
286                 return@runBlocking
287             }
288
289             // then; we should get error in our output properties
290             assertEquals(
291                 ComponentConfigSnapshotsExecutor.OUTPUT_STATUS_ERROR.asJsonPrimitive(),
292                 bluePrintRuntimeService.getNodeTemplateAttributeValue(
293                     nodeTemplateName,
294                     ComponentConfigSnapshotsExecutor.OUTPUT_STATUS
295                 )
296             )
297             val message = "Could not compare config snapshots for type YANG"
298             assertEquals(
299                 message.asJsonPrimitive(),
300                 bluePrintRuntimeService.getNodeTemplateAttributeValue(
301                     nodeTemplateName,
302                     ComponentConfigSnapshotsExecutor.OUTPUT_MESSAGE
303                 )
304             )
305         }
306     }
307
308     @Test
309     fun processNBCompareTwoJsonConfigSnapshots() {
310
311         runBlocking {
312
313             // when; comparing RUNNING vs CANDIDATE json configs; should get an success response; with differences
314             try {
315                 val resId = "131313"
316                 val resType = "PNF"
317                 preparePayload("config-payload-running.json", resId, resType, ResourceConfigSnapshot.Status.RUNNING)
318                 preparePayload("config-payload-candidate.json", resId, resType, ResourceConfigSnapshot.Status.CANDIDATE)
319
320                 prepareRequestProperties(OPERATION_DIFF, resId, resType, DIFF_JSON)
321                 cfgSnapshotComponent.processNB(executionRequest)
322             } catch (e: BluePrintProcessorException) {
323                 kotlin.test.assertEquals(
324                     "Can't proceed with the cfg snapshot diff: provide resource-id and resource-type.",
325                     e.message
326                 )
327                 return@runBlocking
328             }
329
330             // then; we should get success
331             assertTrue(bluePrintRuntimeService.getBluePrintError().errors.size == 0)
332             assertEquals(
333                 ComponentConfigSnapshotsExecutor.OUTPUT_STATUS_SUCCESS.asJsonPrimitive(),
334                 bluePrintRuntimeService.getNodeTemplateAttributeValue(
335                     nodeTemplateName,
336                     ComponentConfigSnapshotsExecutor.OUTPUT_STATUS
337                 )
338             )
339
340             // then; we should get JSON-patches differences in our response property
341             val diffJson =
342                 "[{\"op\":\"add\",\"path\":\"/system-uptime-information/last-configured-time/new-child-object\",\"value\":{\"property\":\"value\"}}," +
343                     "{\"op\":\"replace\",\"path\":\"/system-uptime-information/system-booted-time/time-length\",\"value\":\"14:52:54\"}," +
344                     "{\"op\":\"replace\",\"path\":\"/system-uptime-information/time-source\",\"value\":\" DNS CLOCK \"}," +
345                     "{\"op\":\"add\",\"path\":\"/system-uptime-information/uptime-information/load-average-10\",\"value\":\"0.05\"}]"
346             assertEquals(
347                 diffJson.asJsonPrimitive(),
348                 bluePrintRuntimeService.getNodeTemplateAttributeValue(
349                     nodeTemplateName,
350                     ComponentConfigSnapshotsExecutor.OUTPUT_SNAPSHOT
351                 )
352             )
353         }
354     }
355
356     @Test
357     fun processNBCompareTwoXmlConfigSnapshots() {
358
359         runBlocking {
360
361             // when; comparing RUNNING vs CANDIDATE xml configs; should get an success response; with differences
362             try {
363                 val resId = "141414"
364                 val resType = "VNF"
365                 preparePayload("interface-running.xml", resId, resType, ResourceConfigSnapshot.Status.RUNNING)
366                 preparePayload("interface-candidate.xml", resId, resType, ResourceConfigSnapshot.Status.CANDIDATE)
367
368                 prepareRequestProperties(OPERATION_DIFF, resId, resType, DIFF_XML)
369
370                 cfgSnapshotComponent.processNB(executionRequest)
371             } catch (e: BluePrintProcessorException) {
372                 kotlin.test.assertEquals(
373                     "Can't proceed with the cfg snapshot diff: provide resource-id and resource-type.",
374                     e.message
375                 )
376                 return@runBlocking
377             }
378
379             // then; we should get success
380             assertTrue(bluePrintRuntimeService.getBluePrintError().errors.size == 0)
381             assertEquals(
382                 ComponentConfigSnapshotsExecutor.OUTPUT_STATUS_SUCCESS.asJsonPrimitive(),
383                 bluePrintRuntimeService.getNodeTemplateAttributeValue(
384                     nodeTemplateName,
385                     ComponentConfigSnapshotsExecutor.OUTPUT_STATUS
386                 )
387             )
388
389             // then; we should get XML-patches differences in our response property
390             val diffXml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
391                 "<diff>" +
392                 "<replace sel=\"/output[1]/interface-information[1]/interface-flapped[1]/@seconds\">2343</replace>" +
393                 "<replace sel=\"/output[1]/interface-information[1]/interface-flapped[1]/text()[1]\">34</replace>" +
394                 "<replace sel=\"/output[1]/interface-information[1]/traffic-statistics[1]/input-packets[1]/text()[1]\">09098789</replace>" +
395                 "<replace sel=\"/output[1]/interface-information[1]/traffic-statistics[1]/output-packets[1]/text()[1]\">2828828</replace>" +
396                 "<add sel=\"/output[1]/interface-information[1]/physical-interface[1]\"><interface-name>TEGig400-int01</interface-name></add>" +
397                 "</diff>"
398             assertEquals(
399                 diffXml.asJsonPrimitive(),
400                 bluePrintRuntimeService.getNodeTemplateAttributeValue(
401                     nodeTemplateName,
402                     ComponentConfigSnapshotsExecutor.OUTPUT_SNAPSHOT
403                 )
404             )
405         }
406     }
407
408     private fun preparePayload(
409         filename: String,
410         resId: String,
411         resType: String,
412         status: ResourceConfigSnapshot.Status
413     ) {
414         runBlocking {
415             cfgSnapshotService.write(
416                 JacksonUtils.getClassPathFileContent("payload/requests/$filename"),
417                 resId,
418                 resType,
419                 status
420             )
421         }
422     }
423
424     private fun prepareRequestProperties(oper: String, resId: String, resType: String, optional: String = "") {
425         cfgSnapshotComponent.operationInputs[ComponentConfigSnapshotsExecutor.INPUT_OPERATION] = oper.asJsonPrimitive()
426         cfgSnapshotComponent.operationInputs[ComponentConfigSnapshotsExecutor.INPUT_RESOURCE_ID] =
427             resId.asJsonPrimitive()
428         cfgSnapshotComponent.operationInputs[ComponentConfigSnapshotsExecutor.INPUT_RESOURCE_TYPE] =
429             resType.asJsonPrimitive()
430
431         // Optional inputs
432         cfgSnapshotComponent.operationInputs[ComponentConfigSnapshotsExecutor.INPUT_DIFF_CONTENT_TYPE] =
433             "".asJsonPrimitive()
434         cfgSnapshotComponent.operationInputs[ComponentConfigSnapshotsExecutor.INPUT_RESOURCE_SNAPSHOT] =
435             "".asJsonPrimitive()
436         cfgSnapshotComponent.operationInputs[ComponentConfigSnapshotsExecutor.INPUT_RESOURCE_STATUS] =
437             ResourceConfigSnapshot.Status.RUNNING.name.asJsonPrimitive()
438
439         when (oper) {
440             OPERATION_DIFF ->
441                 cfgSnapshotComponent.operationInputs[ComponentConfigSnapshotsExecutor.INPUT_DIFF_CONTENT_TYPE] =
442                     optional.asJsonPrimitive()
443             OPERATION_STORE ->
444                 cfgSnapshotComponent.operationInputs[ComponentConfigSnapshotsExecutor.INPUT_RESOURCE_SNAPSHOT] =
445                     optional.asJsonPrimitive()
446             OPERATION_FETCH ->
447                 cfgSnapshotComponent.operationInputs[ComponentConfigSnapshotsExecutor.INPUT_RESOURCE_STATUS] =
448                     optional.asJsonPrimitive()
449         }
450     }
451 }