18896f51dc5b5bc09568468644278d978b7aea52
[ccsdk/cds.git] /
1 /*
2  * Copyright © 2017-2018 AT&T Intellectual Property.
3  * Modifications Copyright © 2019 Bell Canada.
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.apps.controllerblueprints.core.utils
19
20 import com.att.eelf.configuration.EELFLogger
21 import com.att.eelf.configuration.EELFManager
22 import kotlinx.coroutines.runBlocking
23 import org.apache.commons.io.FileUtils
24 import org.apache.commons.lang3.StringUtils
25 import org.onap.ccsdk.apps.controllerblueprints.core.BluePrintConstants
26 import org.onap.ccsdk.apps.controllerblueprints.core.BluePrintException
27 import org.onap.ccsdk.apps.controllerblueprints.core.data.ImportDefinition
28 import org.onap.ccsdk.apps.controllerblueprints.core.data.ServiceTemplate
29 import org.onap.ccsdk.apps.controllerblueprints.core.service.BluePrintContext
30 import java.io.File
31 import java.io.FileFilter
32 import java.nio.file.Files
33 import java.nio.file.Path
34 import java.nio.file.Paths
35 import java.nio.file.StandardOpenOption
36 import java.text.MessageFormat
37 import java.time.Instant
38 import java.time.temporal.ChronoUnit
39 import java.time.ZoneId
40 import java.time.format.DateTimeFormatter
41
42
43
44 class BluePrintFileUtils {
45     companion object {
46
47         private val log: EELFLogger = EELFManager.getInstance().getLogger(this::class.toString())
48
49         fun createEmptyBluePrint(basePath: String) {
50
51             val blueprintDir = File(basePath)
52             FileUtils.deleteDirectory(blueprintDir)
53
54             Files.createDirectories(blueprintDir.toPath())
55
56             val metaDataDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_METADATA_DIR))
57             Files.createDirectories(metaDataDir.toPath())
58
59             val metafile = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_METADATA_ENTRY_DEFINITION_FILE))
60             Files.write(metafile.toPath(), getMetaDataContent().toByteArray(), StandardOpenOption.CREATE_NEW)
61
62             val definitionsDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_DEFINITIONS_DIR))
63             Files.createDirectories(definitionsDir.toPath())
64
65             val scriptsDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_SCRIPTS_DIR))
66             Files.createDirectories(scriptsDir.toPath())
67
68             val plansDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_PLANS_DIR))
69             Files.createDirectories(plansDir.toPath())
70
71             val templatesDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_TEMPLATES_DIR))
72             Files.createDirectories(templatesDir.toPath())
73
74         }
75
76         fun copyBluePrint(sourcePath: String, targetPath: String) {
77             val sourceFile = File(sourcePath)
78             val targetFile = File(targetPath)
79             sourceFile.copyRecursively(targetFile, true)
80         }
81
82         fun deleteBluePrintTypes(basePath: String) {
83             val definitionPath = basePath.plus(File.separator).plus(BluePrintConstants.TOSCA_DEFINITIONS_DIR)
84             log.info("deleting definition types under : $definitionPath")
85
86             val definitionDir = File(definitionPath)
87             // Find the Type Definitions
88             val fileFilter = FileFilter { pathname -> pathname.absolutePath.endsWith("_types.json") }
89             // Delete the Type Files
90             definitionDir.listFiles(fileFilter).forEach {
91                 Files.deleteIfExists(it.toPath())
92             }
93         }
94
95         fun populateDefaultImports(blueprintContext: BluePrintContext) {
96             // Get the Default Types
97             val types = arrayListOf(BluePrintConstants.PATH_DATA_TYPES, BluePrintConstants.PATH_ARTIFACT_TYPES,
98                     BluePrintConstants.PATH_NODE_TYPES, BluePrintConstants.PATH_POLICY_TYPES)
99
100             // Clean Type Imports
101             cleanImportTypes(blueprintContext.serviceTemplate)
102
103             val imports = mutableListOf<ImportDefinition>()
104             types.forEach { typeName ->
105                 val import = ImportDefinition()
106                 import.file = BluePrintConstants.TOSCA_DEFINITIONS_DIR.plus("/$typeName.json")
107                 imports.add(import)
108             }
109
110             blueprintContext.serviceTemplate.imports = imports
111         }
112
113         fun cleanImportTypes(serviceTemplate: ServiceTemplate) {
114             // Clean the Type imports
115             val toDeleteTypes = serviceTemplate.imports?.filter {
116                 it.file.endsWith("_types.json")
117             }
118
119             if (toDeleteTypes != null && toDeleteTypes.isNotEmpty()) {
120                 serviceTemplate.imports?.removeAll(toDeleteTypes)
121             }
122         }
123
124         fun writeEnhancedBluePrint(blueprintContext: BluePrintContext) {
125
126             // Write Blueprint Types
127             writeBluePrintTypes(blueprintContext)
128             // Re Populate the Imports
129             populateDefaultImports(blueprintContext)
130             // Rewrite the Entry Definition Files
131             writeEntryDefinitionFile(blueprintContext)
132
133         }
134
135         fun writeBluePrintTypes(blueprintContext: BluePrintContext) {
136
137             val basePath = blueprintContext.rootPath
138             val definitionPath = basePath.plus(File.separator).plus(BluePrintConstants.TOSCA_DEFINITIONS_DIR)
139             val definitionDir = File(definitionPath)
140
141             check(definitionDir.exists()) {
142                 throw BluePrintException("couldn't get definition file under path(${definitionDir.absolutePath})")
143             }
144
145             blueprintContext.serviceTemplate.dataTypes?.let {
146                 val dataTypesContent = JacksonUtils.getWrappedJson(BluePrintConstants.PATH_DATA_TYPES, it.toSortedMap(), true)
147                 writeTypeFile(definitionDir.absolutePath, BluePrintConstants.PATH_DATA_TYPES, dataTypesContent)
148             }
149
150             blueprintContext.serviceTemplate.artifactTypes?.let {
151                 val artifactTypesContent = JacksonUtils.getWrappedJson(BluePrintConstants.PATH_ARTIFACT_TYPES, it.toSortedMap(), true)
152                 writeTypeFile(definitionDir.absolutePath, BluePrintConstants.PATH_ARTIFACT_TYPES, artifactTypesContent)
153             }
154
155             blueprintContext.serviceTemplate.nodeTypes?.let {
156                 val nodeTypesContent = JacksonUtils.getWrappedJson(BluePrintConstants.PATH_NODE_TYPES, it.toSortedMap(), true)
157                 writeTypeFile(definitionDir.absolutePath, BluePrintConstants.PATH_NODE_TYPES, nodeTypesContent)
158             }
159
160             blueprintContext.serviceTemplate.policyTypes?.let {
161                 val nodeTypesContent = JacksonUtils.getWrappedJson(BluePrintConstants.PATH_POLICY_TYPES, it.toSortedMap(), true)
162                 writeTypeFile(definitionDir.absolutePath, BluePrintConstants.PATH_POLICY_TYPES, nodeTypesContent)
163             }
164         }
165
166         fun writeEntryDefinitionFile(blueprintContext: BluePrintContext) {
167
168             val absoluteEntryDefinitionFile = blueprintContext.rootPath.plus(File.separator).plus(blueprintContext.entryDefinition)
169
170             val serviceTemplate = blueprintContext.serviceTemplate
171
172             // Clone the Service Template
173             val writeServiceTemplate = serviceTemplate.clone()
174             writeServiceTemplate.dataTypes = null
175             writeServiceTemplate.artifactTypes = null
176             writeServiceTemplate.policyTypes = null
177             writeServiceTemplate.nodeTypes = null
178
179             // Write the Serivice Template
180             writeDefinitionFile(absoluteEntryDefinitionFile, JacksonUtils.getJson(writeServiceTemplate, true))
181         }
182
183         fun writeDefinitionFile(definitionFile: String, content: String) = runBlocking {
184             val definitionFile = File(definitionFile)
185             // Delete the File If exists
186             Files.deleteIfExists(definitionFile.toPath())
187
188             Files.write(definitionFile.toPath(), content.toByteArray(), StandardOpenOption.CREATE_NEW)
189             check(definitionFile.exists()) {
190                 throw BluePrintException("couldn't write definition file under path(${definitionFile.absolutePath})")
191             }
192         }
193
194         private fun writeTypeFile(definitionPath: String, type: String, content: String) = runBlocking {
195             val typeFile = File(definitionPath.plus(File.separator).plus("$type.json"))
196
197             Files.write(typeFile.toPath(), content.toByteArray(), StandardOpenOption.CREATE_NEW)
198             check(typeFile.exists()) {
199                 throw BluePrintException("couldn't write $type.json file under path(${typeFile.absolutePath})")
200             }
201         }
202
203         private fun getMetaDataContent(): String {
204             return "TOSCA-Meta-File-Version: 1.0.0" +
205                     "\nCSAR-Version: <VERSION>" +
206                     "\nCreated-By: <AUTHOR NAME>" +
207                     "\nEntry-Definitions: Definitions/<BLUEPRINT_NAME>.json" +
208                     "\nTemplate-Tags: <TAGS>"
209         }
210        
211         fun getBluePrintFile(fileName: String, targetPath: Path) : File {
212             val filePath = targetPath.resolve(fileName).toString()
213             val file = File(filePath)
214             check(file.exists()) {
215                 throw BluePrintException("couldn't get definition file under path(${file.absolutePath})")
216             }
217             return file
218         }
219
220         fun getCBAGeneratedFileName(fileName: String, prefix: String): String {
221             val DATE_FORMAT = "yyyyMMddHHmmss"
222             val formatter = DateTimeFormatter.ofPattern(DATE_FORMAT)
223             val datePrefix = Instant.now().atZone(ZoneId.systemDefault()).toLocalDateTime().format(formatter)
224             return MessageFormat.format(prefix, datePrefix, fileName)
225         }
226
227         fun getCbaStorageDirectory(path: String): Path {
228             check(StringUtils.isNotBlank(path)) {
229                 throw BluePrintException("CBA Path is missing.")
230             }
231
232             val fileStorageLocation = Paths.get(path).toAbsolutePath().normalize()
233
234             if (!Files.exists(fileStorageLocation))
235                 Files.createDirectories(fileStorageLocation)
236
237             return fileStorageLocation
238         }
239
240         fun stripFileExtension(fileName: String): String {
241             val dotIndexe = fileName.lastIndexOf('.')
242
243             // In case dot is in first position, we are dealing with a hidden file rather than an extension
244             return if (dotIndexe > 0) fileName.substring(0, dotIndexe) else fileName
245         }
246
247     }
248 }