Migrate ccsdk/apps to ccsdk/cds
[ccsdk/cds.git] / ms / controllerblueprints / modules / service / src / main / kotlin / org / onap / ccsdk / cds / controllerblueprints / service / enhancer / ResourceDefinitionEnhancerService.kt
1 /*
2  * Copyright © 2017-2018 AT&T Intellectual Property.
3  * Modifications Copyright © 2018 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.service.enhancer
19
20 import com.att.eelf.configuration.EELFLogger
21 import com.att.eelf.configuration.EELFManager
22 import kotlinx.coroutines.Deferred
23 import kotlinx.coroutines.async
24 import kotlinx.coroutines.runBlocking
25 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException
26 import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintTypeEnhancerService
27 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintContext
28 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintRuntimeService
29 import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceAssignment
30 import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceDefinition
31 import org.onap.ccsdk.cds.controllerblueprints.resource.dict.utils.ResourceDictionaryUtils
32 import org.onap.ccsdk.cds.controllerblueprints.service.ResourceDefinitionRepoService
33 import org.onap.ccsdk.cds.controllerblueprints.service.utils.BluePrintEnhancerUtils
34 import org.springframework.stereotype.Service
35
36 interface ResourceDefinitionEnhancerService {
37
38     @Throws(BluePrintException::class)
39     fun enhance(bluePrintTypeEnhancerService: BluePrintTypeEnhancerService,
40                 bluePrintRuntimeService: BluePrintRuntimeService<*>): List<ResourceDefinition>
41 }
42
43 @Service
44 class ResourceDefinitionEnhancerServiceImpl(private val resourceDefinitionRepoService: ResourceDefinitionRepoService) :
45         ResourceDefinitionEnhancerService {
46
47     private val log: EELFLogger = EELFManager.getInstance().getLogger(ResourceDefinitionEnhancerService::class.toString())
48
49     companion object {
50         const val ARTIFACT_TYPE_MAPPING_SOURCE: String = "artifact-mapping-resource"
51     }
52
53     // Enhance the Resource Definition
54     // 1. Get the Resource Mapping files from all NodeTemplates.
55     // 2. Get all the Unique Resource assignments from all mapping files
56     // 3. Collect the Resource Definition for Resource Assignment names from database.
57     // 4. Create the Resource Definition under blueprint base path.
58     override fun enhance(bluePrintTypeEnhancerService: BluePrintTypeEnhancerService,
59                          bluePrintRuntimeService: BluePrintRuntimeService<*>): List<ResourceDefinition> {
60
61         var resourceDefinitions: List<ResourceDefinition> = mutableListOf()
62
63         val blueprintContext = bluePrintRuntimeService.bluePrintContext()
64
65         val mappingFiles = getAllResourceMappingFiles(blueprintContext)
66         log.info("resources assignment files ($mappingFiles)")
67         if (mappingFiles != null) {
68             resourceDefinitions = getResourceDefinition(blueprintContext, mappingFiles)
69             // Enriching Resource Definition Sources
70             enrichResourceDefinitionSources(bluePrintRuntimeService.bluePrintContext(), resourceDefinitions)
71         }
72         return resourceDefinitions
73     }
74
75     // Get all the Mapping files from all node templates.
76     private fun getAllResourceMappingFiles(blueprintContext: BluePrintContext): List<String>? {
77
78         return blueprintContext.nodeTemplates()?.mapNotNull { nodeTemplateMap ->
79
80             // Return only Mapping Artifact File Names
81             nodeTemplateMap.value.artifacts?.filter { artifactDefinitionMap ->
82                 artifactDefinitionMap.value.type == ARTIFACT_TYPE_MAPPING_SOURCE
83             }?.mapNotNull { artifactDefinitionMap ->
84                 artifactDefinitionMap.value.file
85             }
86
87         }?.flatten()?.distinct()
88     }
89
90     // Convert file content to ResourceAssignments asynchronously
91     private fun getResourceDefinition(blueprintContext: BluePrintContext, files: List<String>) = runBlocking {
92         val blueprintBasePath = blueprintContext.rootPath
93         val deferredResourceAssignments = mutableListOf<Deferred<List<ResourceAssignment>>>()
94         for (file in files) {
95             log.info("processing file ($file)")
96             deferredResourceAssignments += async {
97                 ResourceDictionaryUtils.getResourceAssignmentFromFile("$blueprintBasePath/$file")
98             }
99         }
100
101         val resourceAssignments = mutableListOf<ResourceAssignment>()
102         for (deferredResourceAssignment in deferredResourceAssignments) {
103             resourceAssignments.addAll(deferredResourceAssignment.await())
104         }
105
106         val distinctResourceAssignments = resourceAssignments.distinctBy { it.name }
107         generateResourceDictionary(blueprintBasePath, distinctResourceAssignments)
108         //log.info("distinct Resource assignment ($distinctResourceAssignments)")
109     }
110
111
112     // Read the Resource Definitions from the Database and write to type file.
113     private fun generateResourceDictionary(blueprintBasePath: String, resourceAssignments: List<ResourceAssignment>)
114             : List<ResourceDefinition> {
115         val resourceKeys = resourceAssignments.mapNotNull { it.dictionaryName }.distinct().sorted()
116         log.info("distinct resource keys ($resourceKeys)")
117
118         //TODO("Optimise DB single Query to multiple Query")
119         return resourceKeys.map { resourceKey ->
120             getResourceDefinition(resourceKey)
121         }
122     }
123
124     private fun enrichResourceDefinitionSources(bluePrintContext: BluePrintContext,
125                                                 resourceDefinitions: List<ResourceDefinition>) {
126         val sources = resourceDefinitions
127                 .map { it.sources }
128                 .map {
129                     it.values
130                             .map { nodeTemplate ->
131                                 nodeTemplate.type
132                             }
133                 }
134                 .flatten().distinct()
135         log.info("Enriching Resource Definition sources Node Template: $sources")
136         sources.forEach {
137             BluePrintEnhancerUtils.populateNodeType(bluePrintContext, resourceDefinitionRepoService, it)
138         }
139     }
140
141     // Get the Resource Definition from Database
142     private fun getResourceDefinition(name: String): ResourceDefinition {
143         return resourceDefinitionRepoService.getResourceDefinition(name)
144     }
145 }