SO-3835 Modify-Config flow of slice (Day-2) -snssai not updated in config map of...
[ccsdk/cds.git] / components / model-catalog / blueprint-model / service-blueprint / 5GC_Simulator_CNF_CDS / Scripts / kotlin / KotlinDayOneConfig.kt
1 /*
2 * Copyright © 2019 TechMahindra
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.services.execution.scripts
18
19 import com.fasterxml.jackson.annotation.JsonIgnore
20 import com.fasterxml.jackson.annotation.JsonProperty
21 import com.fasterxml.jackson.databind.ObjectMapper
22 import com.fasterxml.jackson.databind.node.ObjectNode
23 import com.fasterxml.jackson.databind.JsonNode
24 import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
25 import java.io.File
26 import java.nio.file.Path
27 import java.nio.file.Paths
28 import org.apache.commons.io.FilenameUtils
29 import org.apache.commons.io.IOUtils
30 import org.apache.http.client.ClientProtocolException
31 import org.apache.http.client.entity.EntityBuilder
32 import org.apache.http.client.methods.HttpPost
33 import org.apache.http.client.methods.HttpUriRequest
34 import org.apache.http.entity.ContentType
35 import org.apache.http.message.BasicHeader
36 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput
37 import org.onap.ccsdk.cds.blueprintsprocessor.rest.BasicAuthRestClientProperties
38 import org.onap.ccsdk.cds.blueprintsprocessor.rest.RestClientProperties
39 import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.BasicAuthRestClientService
40 import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.BlueprintWebClientService
41 import org.onap.ccsdk.cds.blueprintsprocessor.core.BluePrintPropertiesService
42 import org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.definition.K8sPluginDefinitionApi
43 import org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.K8sConnectionPluginConfiguration
44 import org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.definition.K8sDefinitionRestClient
45 import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.RestLoggerService
46 import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractScriptComponentFunction
47 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.contentFromResolvedArtifactNB
48 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
49 import org.onap.ccsdk.cds.controllerblueprints.core.utils.ArchiveType
50 import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintArchiveUtils
51 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
52 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.storedContentFromResolvedArtifactNB
53 import org.slf4j.LoggerFactory
54 import org.springframework.http.HttpHeaders
55 import org.springframework.http.HttpMethod
56 import org.springframework.http.MediaType
57 import org.springframework.web.client.RestTemplate
58 import org.yaml.snakeyaml.Yaml
59 import java.util.ArrayList
60 import java.io.IOException
61
62 import java.util.Base64
63 import java.nio.charset.Charset
64 import java.nio.file.Files
65 import com.google.gson.Gson
66 import com.google.gson.reflect.TypeToken
67
68 open class DayOneConfig : AbstractScriptComponentFunction() {
69
70     private val log = LoggerFactory.getLogger(DayOneConfig::class.java)!!
71
72     override fun getName(): String {
73         return "DayOneConfig"
74     }
75
76     override suspend fun processNB(executionRequest: ExecutionServiceInput) {
77         log.info("DAY-1 Script excution Started")
78
79         val prefix = "baseconfig"
80
81         val baseK8sApiUrl = getDynamicProperties("api-access").get("url").asText()
82         val k8sApiUsername = getDynamicProperties("api-access").get("username").asText()
83         val k8sApiPassword = getDynamicProperties("api-access").get("password").asText()
84
85         log.info("Multi-cloud params $baseK8sApiUrl")
86
87         val aaiApiUrl = getDynamicProperties("aai-access").get("url").asText()
88         val aaiApiUsername = getDynamicProperties("aai-access").get("username").asText()
89         val aaiApiPassword = getDynamicProperties("aai-access").get("password").asText()
90
91
92
93         log.info("AAI params $aaiApiUrl")
94
95
96
97
98         val resolution_key = getDynamicProperties("resolution-key").asText()
99
100         val sdnc_payload:String = contentFromResolvedArtifactNB("config-deploy-sdnc")
101         //log.info("SDNC payload $sdnc_payload")
102         val sdnc_payloadObject = JacksonUtils.jsonNode(sdnc_payload) as ObjectNode
103
104
105         val aai_payload:String = contentFromResolvedArtifactNB("config-deploy-aai")
106         //log.info("AAI payload $aai_payload")
107         val aai_payloadObject = JacksonUtils.jsonNode(aai_payload) as ObjectNode
108
109
110
111
112
113
114         try {
115
116             for (item in sdnc_payloadObject.get("vf-modules")){
117
118                 var instanceID:String =""
119                 val modelTopology = item.get("vf-module-data").get("vf-module-topology")
120
121
122
123                 val moduleParameters = modelTopology.get("vf-module-parameters").get("param")
124
125                 val label: String? = getParamValueByName(moduleParameters, "vf-module-label")
126                 val modelInfo = modelTopology.get("onap-model-information")
127                 val vfModuleInvariantID = modelInfo.get("model-invariant-uuid").asText()
128                 log.info("VF MOdule Inavriant ID $vfModuleInvariantID")
129                 val vfModuleCustID=modelInfo.get("model-customization-uuid").asText()
130                 val vfModuleUUID=modelInfo.get("model-uuid").asText()
131                 val idInfo = modelTopology.get("vf-module-topology-identifier")
132                 val vfModuleID = idInfo.get("vf-module-id").asText()
133                 for (aai_item in aai_payloadObject.get("vf-modules"))
134                 {
135                     if (aai_item.get("vf-module-id").asText() == vfModuleID && aai_item.get("heat-stack-id") != null)
136                     {
137                         instanceID=aai_item.get("heat-stack-id").asText()
138                         break
139                     }
140                 }
141
142
143
144                 val k8sRbProfileName: String = "profile_" + vfModuleID
145
146                 val k8sConfigTemplateName: String = "template_" + vfModuleCustID
147
148                 val api = K8sConfigTemplateApi(k8sApiUsername, k8sApiPassword, baseK8sApiUrl, vfModuleInvariantID, vfModuleCustID, k8sConfigTemplateName)
149
150                 // Check if definition exists
151                 if (!api.hasDefinition()) {
152                     throw BluePrintProcessorException("K8S Definition ($vfModuleInvariantID/$vfModuleCustID)  not found ")
153                 }
154                 val bluePrintPropertiesService: BluePrintPropertiesService =this.functionDependencyInstanceAsType("bluePrintPropertiesService")
155                 val k8sConfiguration = K8sConnectionPluginConfiguration(bluePrintPropertiesService)
156                 val rbDefinitionService = K8sDefinitionRestClient(k8sConfiguration,vfModuleInvariantID, vfModuleCustID)
157
158
159                 val def: BlueprintWebClientService.WebClientResponse<String> = rbDefinitionService.exchangeResource(HttpMethod.GET.name,"","")
160                 log.info(def.body.toString())
161                 val rbdef = JacksonUtils.jsonNode(def.body.toString()) as ObjectNode
162                 val chartName = rbdef.get("chart-name").asText()
163
164                 log.info("Config Template name: $k8sConfigTemplateName")
165
166
167
168                 var configTemplate = K8sConfigTemplate()
169                 configTemplate.templateName = k8sConfigTemplateName
170                 configTemplate.description = " "
171                 configTemplate.ChartName = chartName
172                 log.info("Chart name: ${configTemplate.ChartName}")
173
174
175
176                 if (!api.hasConfigTemplate(configTemplate)) {
177
178
179                     val configTemplateFile: Path = prepareConfigTemplateJson(k8sConfigTemplateName, vfModuleID, label)
180
181                     log.info("Config Template Upload Started")
182                     api.createConfigTemplate(configTemplate)
183                     api.uploadConfigTemplateContent(configTemplate, configTemplateFile)
184                     log.info("Config Template Upload Completed")
185                 }
186             }
187             log.info("DAY-1 Script excution completed")
188
189
190         }
191         catch (e: Exception) {
192             log.info("Caught exception during config template preparation!!")
193             throw BluePrintProcessorException("${e.message}")
194         }
195     }
196     private fun getParamValueByName(params: JsonNode, paramName: String): String? {
197         for (param in params) {
198             if (param.get("name").asText() == paramName && param.get("value").asText() != "null") {
199                 return param.get("value").asText()
200
201             }
202         }
203         return null
204     }
205
206     fun prepareConfigTemplateJson(configTemplateName: String, vfModuleID: String, label: String?): Path {
207         val bluePrintContext = bluePrintRuntimeService.bluePrintContext()
208         val bluePrintBasePath: String = bluePrintContext.rootPath
209
210         var profileFilePath: Path = Paths.get(bluePrintBasePath.plus(File.separator).plus("Templates").plus(File.separator).plus("k8s-profiles").plus(File.separator).plus(label +"-config-template.tar.gz"))
211         log.info("Reading K8s Config Template file: $profileFilePath")
212
213         val profileFile = profileFilePath.toFile()
214
215         if (!profileFile.exists())
216             throw BluePrintProcessorException("K8s Config template file $profileFilePath does not exists")
217
218         return profileFilePath
219     }
220
221
222     fun getResolvedParameter(payload: ObjectNode, keyName: String): String {
223         for (node in payload.get("resource-accumulator-resolved-data").elements()) {
224             if (node.get("param-name").asText().equals(keyName)) {
225                 return node.get("param-value").asText()
226             }
227         }
228         return ""
229     }
230     override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) {
231         log.info("Recover function called!")
232         log.info("Execution request : $executionRequest")
233         log.error("Exception", runtimeException)
234         addError(runtimeException.message!!)
235     }
236
237
238
239     inner class K8sConfigTemplateApi(
240             val username: String,
241             val password: String,
242             val baseUrl: String,
243             val definition: String,
244             val definitionVersion: String,
245             val configTemplateName: String
246     ) {
247         private val service: UploadConfigTemplateRestClientService // BasicAuthRestClientService
248
249         init {
250             var mapOfHeaders = hashMapOf<String, String>()
251             mapOfHeaders.put("Accept", "application/json")
252             mapOfHeaders.put("Content-Type", "application/json")
253             mapOfHeaders.put("cache-control", " no-cache")
254             mapOfHeaders.put("Accept", "application/json")
255             var basicAuthRestClientProperties: BasicAuthRestClientProperties = BasicAuthRestClientProperties()
256             basicAuthRestClientProperties.username = username
257             basicAuthRestClientProperties.password = password
258             basicAuthRestClientProperties.url = "$baseUrl/v1/rb/definition/$definition/$definitionVersion"
259             basicAuthRestClientProperties.additionalHeaders = mapOfHeaders
260
261             this.service = UploadConfigTemplateRestClientService(basicAuthRestClientProperties)
262         }
263
264         fun hasDefinition(): Boolean {
265             try {
266                 val result: BlueprintWebClientService.WebClientResponse<String> = service.exchangeResource(HttpMethod.GET.name, "", "")
267                 print(result)
268                 if (result.status >= 200 && result.status < 300)
269                     return true
270                 else
271                     return false
272             } catch (e: Exception) {
273                 log.info("Caught exception trying to get k8s config trmplate  definition")
274                 throw BluePrintProcessorException("${e.message}")
275             }
276         }
277
278         fun hasConfigTemplate(profile: K8sConfigTemplate): Boolean {
279             try {
280                 val result: BlueprintWebClientService.WebClientResponse<String> = service.exchangeResource(HttpMethod.GET.name, "/config-template/${profile.templateName}", "")
281                 print(result)
282                 if (result.status >= 200 && result.status < 300) {
283                     log.info("ConfigTemplate already exists")
284                     return true
285                 } else
286                     return false
287             } catch (e: Exception) {
288                 log.info("Caught exception trying to get k8s config trmplate  definition")
289                 throw BluePrintProcessorException("${e.message}")
290             }
291         }
292
293         fun createConfigTemplate(profile: K8sConfigTemplate) {
294             val objectMapper = ObjectMapper()
295             val profileJsonString: String = objectMapper.writeValueAsString(profile)
296             try {
297                 val result: BlueprintWebClientService.WebClientResponse<String> = service.exchangeResource(
298                         HttpMethod.POST.name,
299                         "/config-template",
300                         profileJsonString
301                 )
302
303                 if (result.status >= 200 && result.status < 300) {
304                     log.info("Config template json info uploaded correctly")
305                 } else if (result.status < 200 || result.status >= 300) {
306                     log.info("Config template already exists")
307                 }
308             } catch (e: Exception) {
309                 log.info("Caught exception trying to create k8s config template ${profile.templateName}  - updated")
310                 //    throw BluePrintProcessorException("${e.message}")
311             }
312         }
313
314         fun uploadConfigTemplateContent(profile: K8sConfigTemplate, filePath: Path) {
315             try {
316                 val result: BlueprintWebClientService.WebClientResponse<String> = service.uploadBinaryFile(
317                         "/config-template/${profile.templateName}/content",
318                         filePath
319                 )
320                 if (result.status < 200 || result.status >= 300) {
321                     throw Exception(result.body)
322                 }
323             } catch (e: Exception) {
324                 log.info("Caught exception trying to upload k8s config template ${profile.templateName}")
325                 throw BluePrintProcessorException("${e.message}")
326             }
327         }
328     }
329 }
330
331 class UploadConfigTemplateRestClientService(
332         private val restClientProperties:
333         BasicAuthRestClientProperties
334 ) : BlueprintWebClientService {
335
336     override fun defaultHeaders(): Map<String, String> {
337
338         val encodedCredentials = setBasicAuth(
339                 restClientProperties.username,
340                 restClientProperties.password
341         )
342         return mapOf(
343                 HttpHeaders.CONTENT_TYPE to MediaType.APPLICATION_JSON_VALUE,
344                 HttpHeaders.ACCEPT to MediaType.APPLICATION_JSON_VALUE,
345                 HttpHeaders.AUTHORIZATION to "Basic $encodedCredentials"
346         )
347     }
348
349     override fun host(uri: String): String {
350         return restClientProperties.url + uri
351     }
352
353     override fun convertToBasicHeaders(headers: Map<String, String>):
354             Array<BasicHeader> {
355         val customHeaders: MutableMap<String, String> = headers.toMutableMap()
356         // inject additionalHeaders
357         customHeaders.putAll(verifyAdditionalHeaders(restClientProperties))
358
359         if (!headers.containsKey(HttpHeaders.AUTHORIZATION)) {
360             val encodedCredentials = setBasicAuth(
361                     restClientProperties.username,
362                     restClientProperties.password
363             )
364             customHeaders[HttpHeaders.AUTHORIZATION] =
365                     "Basic $encodedCredentials"
366         }
367         return super.convertToBasicHeaders(customHeaders)
368     }
369
370     private fun setBasicAuth(username: String, password: String): String {
371         val credentialsString = "$username:$password"
372         return Base64.getEncoder().encodeToString(
373                 credentialsString.toByteArray(Charset.defaultCharset())
374         )
375     }
376
377     @Throws(IOException::class, ClientProtocolException::class)
378     private fun performHttpCall(httpUriRequest: HttpUriRequest): BlueprintWebClientService.WebClientResponse<String> {
379         val httpResponse = httpClient().execute(httpUriRequest)
380         val statusCode = httpResponse.statusLine.statusCode
381         httpResponse.entity.content.use {
382             val body = IOUtils.toString(it, Charset.defaultCharset())
383             return BlueprintWebClientService.WebClientResponse(statusCode, body)
384         }
385     }
386
387     fun uploadBinaryFile(path: String, filePath: Path): BlueprintWebClientService.WebClientResponse<String> {
388         val convertedHeaders: Array<BasicHeader> = convertToBasicHeaders(defaultHeaders())
389         val httpPost = HttpPost(host(path))
390         val entity = EntityBuilder.create().setBinary(Files.readAllBytes(filePath)).build()
391         httpPost.setEntity(entity)
392         RestLoggerService.httpInvoking(convertedHeaders)
393         httpPost.setHeaders(convertedHeaders)
394         return performHttpCall(httpPost)
395     }
396 }
397
398 class K8sConfigTemplate {
399     @get:JsonProperty("template-name")
400     var templateName: String? = null
401     @get:JsonProperty("description")
402     var description: String? = null
403     @get:JsonProperty("ChartName")
404     var ChartName: String? = null
405
406     override fun equals(other: Any?): Boolean {
407         if (this === other) return true
408         if (javaClass != other?.javaClass) return false
409         return true
410     }
411
412     override fun hashCode(): Int {
413         return javaClass.hashCode()
414     }
415 }
416
417 class K8sResources {
418
419     var GVK: GVK? = null
420     lateinit var Name: String
421
422 }
423
424 class GVK {
425
426     var Group: String? = null
427     var Version: String? = null
428     var Kind: String? = null
429
430 }
431
432 fun main(args: Array<String>) {
433
434     val kotlin = DayOneConfig()
435
436
437
438 }