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