Removed redundant timeout handling for executeCommand
[ccsdk/cds.git] / ms / blueprintsprocessor / modules / blueprints / blueprint-core / src / main / kotlin / org / onap / ccsdk / cds / controllerblueprints / core / utils / BluePrintMetadataUtils.kt
1 /*
2  * Copyright © 2017-2018 AT&T Intellectual Property.
3  * Modifications Copyright © 2018-2019 IBM.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 package org.onap.ccsdk.cds.controllerblueprints.core.utils
19
20 import com.fasterxml.jackson.databind.JsonNode
21 import kotlinx.coroutines.runBlocking
22 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
23 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException
24 import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive
25 import org.onap.ccsdk.cds.controllerblueprints.core.checkNotEmpty
26 import org.onap.ccsdk.cds.controllerblueprints.core.data.ServiceTemplate
27 import org.onap.ccsdk.cds.controllerblueprints.core.data.ToscaMetaData
28 import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintDefinitions
29 import org.onap.ccsdk.cds.controllerblueprints.core.normalizedFile
30 import org.onap.ccsdk.cds.controllerblueprints.core.normalizedPathName
31 import org.onap.ccsdk.cds.controllerblueprints.core.readNBLines
32 import org.onap.ccsdk.cds.controllerblueprints.core.scripts.BluePrintScriptsServiceImpl
33 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintContext
34 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintImportService
35 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintRuntimeService
36 import org.onap.ccsdk.cds.controllerblueprints.core.service.DefaultBluePrintRuntimeService
37 import org.slf4j.LoggerFactory
38 import java.io.File
39 import java.util.Properties
40
41 class BluePrintMetadataUtils {
42     companion object {
43
44         private val log = LoggerFactory.getLogger(this::class.toString())
45
46         suspend fun toscaMetaData(basePath: String): ToscaMetaData {
47             val toscaMetaPath = basePath.plus(BluePrintConstants.PATH_DIVIDER)
48                 .plus(BluePrintConstants.TOSCA_METADATA_ENTRY_DEFINITION_FILE)
49             return toscaMetaDataFromMetaFile(toscaMetaPath)
50         }
51
52         suspend fun entryDefinitionFile(basePath: String): String {
53             val toscaMetaPath = basePath.plus(BluePrintConstants.PATH_DIVIDER)
54                 .plus(BluePrintConstants.TOSCA_METADATA_ENTRY_DEFINITION_FILE)
55             return toscaMetaDataFromMetaFile(toscaMetaPath).entityDefinitions
56         }
57
58         fun bluePrintEnvProperties(basePath: String): Properties {
59             val blueprintsEnvFilePath = basePath.plus(File.separator)
60                 .plus(BluePrintConstants.TOSCA_ENVIRONMENTS_DIR)
61             return environmentFileProperties(blueprintsEnvFilePath)
62         }
63
64         fun environmentFileProperties(pathName: String): Properties {
65             val properties = Properties()
66             val envDir = normalizedFile(pathName)
67             // Verify if the environment directory exists
68             if (envDir.exists() && envDir.isDirectory) {
69                 // Find all available environment files
70                 envDir.listFiles()!!
71                     .filter { it.name.endsWith(".properties") }
72                     .forEach {
73                         val istream = it.inputStream()
74                         properties.load(istream)
75                         istream.close()
76                     }
77             }
78             return properties
79         }
80
81         private suspend fun toscaMetaDataFromMetaFile(metaFilePath: String): ToscaMetaData {
82             val toscaMetaData = ToscaMetaData()
83             val lines = normalizedFile(metaFilePath).readNBLines()
84             lines.forEach { line ->
85                 if (line.contains(":")) {
86                     val keyValue = line.split(":")
87                     if (keyValue.size == 2) {
88                         val value: String = keyValue[1].trim()
89                         when (keyValue[0]) {
90                             "TOSCA-Meta-File-Version" -> toscaMetaData.toscaMetaFileVersion = value
91                             "CSAR-Version" -> toscaMetaData.csarVersion = value
92                             "Created-By" -> toscaMetaData.createdBy = value
93                             "Entry-Definitions" -> toscaMetaData.entityDefinitions = value
94                             "Template-Name" -> toscaMetaData.templateName = value
95                             "Template-Version" -> toscaMetaData.templateVersion = value
96                             "Template-Tags" -> toscaMetaData.templateTags = value
97                             "Template-Type" -> toscaMetaData.templateType = value
98                         }
99                     }
100                 }
101             }
102             return toscaMetaData
103         }
104
105         /** Get the default blueprint runtime for [id] and [blueprintBasePath] */
106         suspend fun getBluePrintRuntime(id: String, blueprintBasePath: String):
107             BluePrintRuntimeService<MutableMap<String, JsonNode>> {
108                 val bluePrintContext: BluePrintContext = getBluePrintContext(blueprintBasePath)
109                 return getBluePrintRuntime(id, bluePrintContext)
110             }
111
112         /** Get the default blocking blueprint runtime api for [id] and [blueprintBasePath] used in testing */
113         fun bluePrintRuntime(id: String, blueprintBasePath: String):
114             BluePrintRuntimeService<MutableMap<String, JsonNode>> = runBlocking {
115                 val bluePrintContext: BluePrintContext = getBluePrintContext(blueprintBasePath)
116                 getBluePrintRuntime(id, bluePrintContext)
117             }
118
119         /** Get the default blueprint runtime from [bluePrintContext] */
120         fun getBluePrintRuntime(id: String, bluePrintContext: BluePrintContext):
121             BluePrintRuntimeService<MutableMap<String, JsonNode>> {
122                 checkNotEmpty(bluePrintContext.rootPath) { "blueprint context root path is missing." }
123                 checkNotEmpty(bluePrintContext.entryDefinition) { "blueprint context entry definition is missing." }
124                 val blueprintBasePath = bluePrintContext.rootPath
125                 val bluePrintRuntimeService = DefaultBluePrintRuntimeService(id, bluePrintContext)
126                 bluePrintRuntimeService.put(
127                     BluePrintConstants.PROPERTY_BLUEPRINT_BASE_PATH,
128                     blueprintBasePath.asJsonPrimitive()
129                 )
130                 bluePrintRuntimeService.put(BluePrintConstants.PROPERTY_BLUEPRINT_PROCESS_ID, id.asJsonPrimitive())
131                 return bluePrintRuntimeService
132             }
133
134         /** Get the blueprint runtime for enhancement start for [id] and [blueprintBasePath] */
135         suspend fun getBaseEnhancementBluePrintRuntime(id: String, blueprintBasePath: String):
136             BluePrintRuntimeService<MutableMap<String, JsonNode>> {
137
138                 val bluePrintContext: BluePrintContext = getBaseEnhancementBluePrintContext(blueprintBasePath)
139
140                 val bluePrintRuntimeService = DefaultBluePrintRuntimeService(id, bluePrintContext)
141                 bluePrintRuntimeService.put(
142                     BluePrintConstants.PROPERTY_BLUEPRINT_BASE_PATH,
143                     blueprintBasePath.asJsonPrimitive()
144                 )
145                 bluePrintRuntimeService.put(BluePrintConstants.PROPERTY_BLUEPRINT_PROCESS_ID, id.asJsonPrimitive())
146
147                 return bluePrintRuntimeService
148             }
149
150         /** Get the default blueprint runtime for enhancement start for [id],  [blueprintBasePath] and [executionContext] */
151         suspend fun getBluePrintRuntime(
152             id: String,
153             blueprintBasePath: String,
154             executionContext: MutableMap<String, JsonNode>
155         ):
156             BluePrintRuntimeService<MutableMap<String, JsonNode>> {
157                 val bluePrintContext: BluePrintContext = getBluePrintContext(blueprintBasePath)
158                 val bluePrintRuntimeService = DefaultBluePrintRuntimeService(id, bluePrintContext)
159                 executionContext.forEach {
160                     bluePrintRuntimeService.put(it.key, it.value)
161                 }
162
163                 bluePrintRuntimeService.setExecutionContext(executionContext)
164                 return bluePrintRuntimeService
165             }
166
167         /** Get the default blueprint context for [blueprintBasePath]*/
168         suspend fun getBluePrintContext(blueprintBasePath: String): BluePrintContext {
169
170             val toscaMetaData: ToscaMetaData = toscaMetaData(blueprintBasePath)
171
172             log.info(
173                 "Reading blueprint type(${toscaMetaData.templateType}) path($blueprintBasePath) " +
174                     "and entry definition file (${toscaMetaData.entityDefinitions})"
175             )
176
177             // If the EntryDefinition is Kotlin file, compile and get Service Template
178             val bluePrintContext = when (toscaMetaData.templateType.toUpperCase()) {
179                 BluePrintConstants.BLUEPRINT_TYPE_KOTLIN_DSL -> readBlueprintKotlinFile(
180                     toscaMetaData,
181                     blueprintBasePath
182                 )
183                 BluePrintConstants.BLUEPRINT_TYPE_GENERIC_SCRIPT -> readBlueprintGenericScript(
184                     toscaMetaData,
185                     blueprintBasePath
186                 )
187                 BluePrintConstants.BLUEPRINT_TYPE_DEFAULT -> readBlueprintFile(
188                     toscaMetaData.entityDefinitions,
189                     blueprintBasePath
190                 )
191                 else ->
192                     throw BluePrintException(
193                         "Unknown blueprint type(${toscaMetaData.templateType}), " +
194                             "It should be any one of these types[${BluePrintConstants.BLUEPRINT_TYPE_KOTLIN_DSL}," +
195                             "${BluePrintConstants.BLUEPRINT_TYPE_GENERIC_SCRIPT}, " +
196                             "${BluePrintConstants.BLUEPRINT_TYPE_DEFAULT}]"
197                     )
198             }
199             // Copy the metadata info
200             copyMetaInfoToServiceTemplate(toscaMetaData, bluePrintContext.serviceTemplate)
201
202             return bluePrintContext
203         }
204
205         private suspend fun getBaseEnhancementBluePrintContext(blueprintBasePath: String): BluePrintContext {
206             val toscaMetaData: ToscaMetaData = toscaMetaData(blueprintBasePath)
207
208             // Clean Type files
209             BluePrintFileUtils.deleteBluePrintTypes(blueprintBasePath)
210             val rootFilePath: String = blueprintBasePath.plus(File.separator).plus(toscaMetaData.entityDefinitions)
211             val rootServiceTemplate = ServiceTemplateUtils.getServiceTemplate(rootFilePath)
212
213             // Copy the metadata info
214             copyMetaInfoToServiceTemplate(toscaMetaData, rootServiceTemplate)
215
216             // Clean the Import Definitions
217             BluePrintFileUtils.cleanImportTypes(rootServiceTemplate)
218
219             val blueprintContext = BluePrintContext(rootServiceTemplate)
220             blueprintContext.rootPath = blueprintBasePath
221             blueprintContext.entryDefinition = toscaMetaData.entityDefinitions
222             return blueprintContext
223         }
224
225         /** copy metadata defined in [toscaMetaData] to [serviceTemplate] */
226         private fun copyMetaInfoToServiceTemplate(toscaMetaData: ToscaMetaData, serviceTemplate: ServiceTemplate) {
227             if (serviceTemplate.metadata == null) serviceTemplate.metadata = mutableMapOf()
228             val metadata = serviceTemplate.metadata!!
229             metadata[BluePrintConstants.METADATA_TEMPLATE_AUTHOR] = toscaMetaData.createdBy
230             metadata[BluePrintConstants.METADATA_TEMPLATE_NAME] = toscaMetaData.templateName
231             metadata[BluePrintConstants.METADATA_TEMPLATE_VERSION] = toscaMetaData.templateVersion
232             metadata[BluePrintConstants.METADATA_TEMPLATE_TAGS] = toscaMetaData.templateTags
233             metadata[BluePrintConstants.METADATA_TEMPLATE_TYPE] = toscaMetaData.templateType
234         }
235
236         private suspend fun readBlueprintFile(entityDefinitions: String, basePath: String): BluePrintContext {
237             val normalizedBasePath = normalizedPathName(basePath)
238             val rootFilePath = normalizedPathName(normalizedBasePath, entityDefinitions)
239             val rootServiceTemplate = ServiceTemplateUtils.getServiceTemplate(rootFilePath)
240
241             // Recursively Import Template files
242             val schemaImportResolverUtils = BluePrintImportService(rootServiceTemplate, normalizedBasePath)
243             val completeServiceTemplate = schemaImportResolverUtils.getImportResolvedServiceTemplate()
244             val blueprintContext = BluePrintContext(completeServiceTemplate)
245             blueprintContext.rootPath = normalizedBasePath
246             blueprintContext.entryDefinition = entityDefinitions
247             return blueprintContext
248         }
249
250         /** Reade the Service Template Definitions from the Kotlin file */
251         private suspend fun readBlueprintKotlinFile(toscaMetaData: ToscaMetaData, basePath: String): BluePrintContext {
252
253             val definitionClassName = toscaMetaData.entityDefinitions.removeSuffix(".kt")
254             val normalizedBasePath = normalizedPathName(basePath)
255
256             val bluePrintScriptsService = BluePrintScriptsServiceImpl()
257             val bluePrintDefinitions = bluePrintScriptsService
258                 .scriptInstance<BluePrintDefinitions>(
259                     normalizedBasePath, toscaMetaData.templateName,
260                     toscaMetaData.templateVersion, definitionClassName, false
261                 )
262             // Get the Service Template
263             val serviceTemplate = bluePrintDefinitions.serviceTemplate()
264
265             // Clean the Default type import Definitions
266             BluePrintFileUtils.cleanImportTypes(serviceTemplate)
267
268             val blueprintContext = BluePrintContext(serviceTemplate)
269             blueprintContext.rootPath = normalizedBasePath
270             blueprintContext.entryDefinition = toscaMetaData.entityDefinitions
271             blueprintContext.otherDefinitions = bluePrintDefinitions.otherDefinitions()
272             return blueprintContext
273         }
274
275         /** Reade the Service Template Definitions from the generic script types */
276         private fun readBlueprintGenericScript(toscaMetaData: ToscaMetaData, basePath: String): BluePrintContext {
277             return BluePrintContext(ServiceTemplate())
278         }
279     }
280 }