[vFW_CNF_CDS] Improve logging and fix tests typo
[demo.git] / heat / vFW_CNF_CDS / templates / cba / Scripts / kotlin / K8sHealthCheck.kt
1 /*
2  * Copyright (C) 2021 Samsung Electronics
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *     http://www.apache.org/licenses/LICENSE-2.0
7  * Unless required by applicable law or agreed to in writing, software
8  * distributed under the License is distributed on an "AS IS" BASIS,
9  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10  * See the License for the specific language governing permissions and
11  * limitations under the License
12  */
13 package org.onap.ccsdk.cds.blueprintsprocessor.services.execution.scripts
14
15 import com.fasterxml.jackson.databind.node.ObjectNode
16 import kotlinx.coroutines.Job
17 import kotlinx.coroutines.cancel
18 import kotlinx.coroutines.delay
19 import kotlinx.coroutines.joinAll
20 import kotlinx.coroutines.launch
21 import kotlinx.coroutines.runBlocking
22 import org.onap.ccsdk.cds.blueprintsprocessor.core.BlueprintPropertiesService
23 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput
24 import org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.K8sConnectionPluginConfiguration
25 import org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.instance.K8sPluginInstanceApi
26 import org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.instance.healthcheck.K8sRbInstanceHealthCheck
27 import org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.instance.healthcheck.K8sRbInstanceHealthCheckSimple
28 import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractScriptComponentFunction
29 import org.slf4j.LoggerFactory
30
31 open class K8sHealthCheck : AbstractScriptComponentFunction() {
32
33     private val log = LoggerFactory.getLogger(K8sHealthCheck::class.java)!!
34
35     override fun getName(): String {
36         return "K8sHealthCheck"
37     }
38
39     private fun initPluginApi(): K8sPluginInstanceApi {
40         val bluePrintPropertiesService: BlueprintPropertiesService = this.functionDependencyInstanceAsType("blueprintPropertiesService")!!
41         val k8sConfiguration = K8sConnectionPluginConfiguration(bluePrintPropertiesService)
42
43         return K8sPluginInstanceApi(k8sConfiguration)
44     }
45
46     override suspend fun processNB(executionRequest: ExecutionServiceInput) {
47         val instanceApi = initPluginApi()
48
49         log.info("Health check script execution - START")
50         val configValueSetup: ObjectNode = getDynamicProperties("config-deploy-setup") as ObjectNode
51         log.info("Config Value Setup: $configValueSetup")
52
53         val instanceHealthCheckList = startInstanceHealthCheck(configValueSetup, instanceApi)
54         val statuses = getStatuses(instanceHealthCheckList, instanceApi)
55         log.info("Health check script execution - END")
56     }
57
58     private fun startInstanceHealthCheck(configValueSetup: ObjectNode, instanceApi: K8sPluginInstanceApi): List<HealthCheckInstance> {
59         val healthCheckInstanceList = arrayListOf<HealthCheckInstance>()
60
61         configValueSetup.fields().forEach {
62             val instanceName = it.value.get("k8s-instance-id").asText()
63             val response: K8sRbInstanceHealthCheckSimple? = instanceApi.startInstanceHealthCheck(instanceName)
64             log.debug("K8sRbInstanceHealthCheckSimple response: $$response")
65             healthCheckInstanceList.add(HealthCheckInstance(instanceName, response?.id))
66         }
67         log.info("healthCheckInstanceList: $healthCheckInstanceList")
68
69         return healthCheckInstanceList
70     }
71
72     private fun getStatuses(instanceHealthCheckList: List<HealthCheckInstance>, instanceApi: K8sPluginInstanceApi): Map<String, String> {
73         val statuses = hashMapOf<String, String>()
74         runBlocking {
75             val jobs: List<Job> = instanceHealthCheckList.map {
76                 launch {
77                     log.info("Thread started: ${Thread.currentThread().name} for $it")
78                     // WAIT APPROX 5 MINUTES
79                     repeat(30) { _ ->
80                         val response: K8sRbInstanceHealthCheck = instanceApi.getInstanceHealthCheck(it.heatStackId, it.healthCheckInstance!!)!!
81                         log.debug("Response for $it: $response")
82                         val status = response.status!!
83                         if (!"RUNNING".equals(status, true)) {
84                             statuses[it.heatStackId] = status
85                             log.info("Poll status: $status for $it")
86                             instanceApi.deleteInstanceHealthCheck(it.heatStackId, it.healthCheckInstance)
87                             cancel()
88                         }
89                         delay(10_000L)
90                     }
91                     statuses[it.heatStackId] = "Timeout"
92                     log.warn("Send delete hc request")
93                     instanceApi.deleteInstanceHealthCheck(it.heatStackId, it.healthCheckInstance!!)
94                 }
95             }
96             jobs.joinAll()
97         }
98         var success = true
99         statuses?.forEach { it ->
100             if (it.value != "Succeeded") {
101                 success = false
102             }
103         }
104         log.info("---")
105         if (success) {
106             log.info("Healthcheck finished successfully")
107         } else {
108             log.info("Healthcheck finished with failure")
109         }
110         log.info("Detailed results: $statuses")
111         log.info("---")
112         return statuses
113     }
114
115     data class HealthCheckInstance(val heatStackId: String, val healthCheckInstance: String?) {
116         override fun toString(): String {
117             return "HealthCheckInstance(heatStackId='$heatStackId', healthCheckInstance='$healthCheckInstance')"
118         }
119     }
120
121     override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) {
122         log.info("Executing Recovery")
123         bluePrintRuntimeService.getBlueprintError().addError("${runtimeException.message}", getName())
124     }
125 }