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