48415efa45ff5239ac49a3f3763c03d0fb36af5e
[ccsdk/apps.git] /
1 /*\r
2  *  Copyright © 2017-2018 AT&T Intellectual Property.\r
3  *  Modifications Copyright © 2018 IBM.\r
4  *\r
5  *  Licensed under the Apache License, Version 2.0 (the "License");\r
6  *  you may not use this file except in compliance with the License.\r
7  *  You may obtain a copy of the License at\r
8  *\r
9  *      http://www.apache.org/licenses/LICENSE-2.0\r
10  *\r
11  *  Unless required by applicable law or agreed to in writing, software\r
12  *  distributed under the License is distributed on an "AS IS" BASIS,\r
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
14  *  See the License for the specific language governing permissions and\r
15  *  limitations under the License.\r
16  */\r
17 \r
18 package org.onap.ccsdk.apps.blueprintsprocessor.functions.resource.resolution\r
19 \r
20 import org.onap.ccsdk.apps.blueprintsprocessor.functions.resource.resolution.processor.ResourceAssignmentProcessor\r
21 import org.onap.ccsdk.apps.blueprintsprocessor.functions.resource.resolution.utils.ResourceAssignmentUtils\r
22 import org.onap.ccsdk.apps.controllerblueprints.core.BluePrintConstants\r
23 import org.onap.ccsdk.apps.controllerblueprints.core.BluePrintProcessorException\r
24 import org.onap.ccsdk.apps.controllerblueprints.core.checkNotEmptyOrThrow\r
25 import org.onap.ccsdk.apps.controllerblueprints.core.service.BluePrintRuntimeService\r
26 import org.onap.ccsdk.apps.controllerblueprints.core.service.BluePrintTemplateService\r
27 import org.onap.ccsdk.apps.controllerblueprints.core.utils.JacksonUtils\r
28 import org.onap.ccsdk.apps.controllerblueprints.resource.dict.ResourceAssignment\r
29 import org.onap.ccsdk.apps.controllerblueprints.resource.dict.ResourceDefinition\r
30 import org.onap.ccsdk.apps.controllerblueprints.resource.dict.utils.BulkResourceSequencingUtils\r
31 import org.slf4j.LoggerFactory\r
32 import org.springframework.context.ApplicationContext\r
33 import org.springframework.stereotype.Service\r
34 import java.io.File\r
35 \r
36 interface ResourceResolutionService {\r
37 \r
38     fun registeredResourceSources(): List<String>\r
39 \r
40     fun resolveResources(bluePrintRuntimeService: BluePrintRuntimeService<*>, nodeTemplateName: String,\r
41                          artifactNames: List<String>): MutableMap<String, String>\r
42 \r
43     fun resolveResources(bluePrintRuntimeService: BluePrintRuntimeService<*>, nodeTemplateName: String,\r
44                          artifactPrefix: String): String\r
45 \r
46     fun resolveResources(bluePrintRuntimeService: BluePrintRuntimeService<*>, nodeTemplateName: String,\r
47                          artifactMapping: String, artifactTemplate: String?): String\r
48 \r
49     fun resolveResourceAssignments(blueprintRuntimeService: BluePrintRuntimeService<*>,\r
50                                    resourceDictionaries: MutableMap<String, ResourceDefinition>,\r
51                                    resourceAssignments: MutableList<ResourceAssignment>,\r
52                                    identifierName: String)\r
53 }\r
54 \r
55 @Service(ResourceResolutionConstants.SERVICE_RESOURCE_RESOLUTION)\r
56 open class ResourceResolutionServiceImpl(private var applicationContext: ApplicationContext) :\r
57         ResourceResolutionService {\r
58 \r
59     private val log = LoggerFactory.getLogger(ResourceResolutionService::class.java)\r
60 \r
61     override fun registeredResourceSources(): List<String> {\r
62         return applicationContext.getBeanNamesForType(ResourceAssignmentProcessor::class.java)\r
63                 .filter { it.startsWith(ResourceResolutionConstants.PREFIX_RESOURCE_RESOLUTION_PROCESSOR) }\r
64                 .map { it.substringAfter(ResourceResolutionConstants.PREFIX_RESOURCE_RESOLUTION_PROCESSOR) }\r
65     }\r
66 \r
67     override fun resolveResources(bluePrintRuntimeService: BluePrintRuntimeService<*>, nodeTemplateName: String,\r
68                                   artifactNames: List<String>): MutableMap<String, String> {\r
69 \r
70         val resolvedParams: MutableMap<String, String> = hashMapOf()\r
71         artifactNames.forEach { artifactName ->\r
72             val resolvedContent = resolveResources(bluePrintRuntimeService, nodeTemplateName, artifactName)\r
73             resolvedParams[artifactName] = resolvedContent\r
74         }\r
75         return resolvedParams\r
76     }\r
77 \r
78     override fun resolveResources(bluePrintRuntimeService: BluePrintRuntimeService<*>, nodeTemplateName: String,\r
79                                   artifactPrefix: String): String {\r
80 \r
81         // Velocity Artifact Definition Name\r
82         val artifactTemplate = "$artifactPrefix-template"\r
83         // Resource Assignment Artifact Definition Name\r
84         val artifactMapping = "$artifactPrefix-mapping"\r
85 \r
86         return resolveResources(bluePrintRuntimeService, nodeTemplateName, artifactMapping, artifactTemplate)\r
87     }\r
88 \r
89 \r
90     override fun resolveResources(bluePrintRuntimeService: BluePrintRuntimeService<*>, nodeTemplateName: String,\r
91                                   artifactMapping: String, artifactTemplate: String?): String {\r
92 \r
93         var resolvedContent = ""\r
94         log.info("Resolving resource for template artifact($artifactTemplate) with resource assignment artifact($artifactMapping)")\r
95 \r
96         val identifierName = artifactTemplate ?: "no-template"\r
97 \r
98         val resourceAssignmentContent = bluePrintRuntimeService.resolveNodeTemplateArtifact(nodeTemplateName, artifactMapping)\r
99 \r
100         val resourceAssignments: MutableList<ResourceAssignment> = JacksonUtils.getListFromJson(resourceAssignmentContent, ResourceAssignment::class.java)\r
101                 as? MutableList<ResourceAssignment>\r
102                 ?: throw BluePrintProcessorException("couldn't get Dictionary Definitions")\r
103 \r
104         // Get the Resource Dictionary Name\r
105         val dictionaryFile = bluePrintRuntimeService.bluePrintContext().rootPath.plus(File.separator)\r
106                 .plus(BluePrintConstants.TOSCA_DEFINITIONS_DIR).plus(File.separator)\r
107                 .plus(ResourceResolutionConstants.FILE_NAME_RESOURCE_DEFINITION_TYPES)\r
108 \r
109         val resourceDictionaries: MutableMap<String, ResourceDefinition> = JacksonUtils.getMapFromFile(dictionaryFile, ResourceDefinition::class.java)\r
110                 ?: throw BluePrintProcessorException("couldn't get Dictionary Definitions")\r
111 \r
112         // Resolve resources\r
113         resolveResourceAssignments(bluePrintRuntimeService, resourceDictionaries, resourceAssignments, identifierName)\r
114 \r
115         val resolvedParamJsonContent = ResourceAssignmentUtils.generateResourceDataForAssignments(resourceAssignments.toList())\r
116 \r
117         // Check Template is there\r
118         if (artifactTemplate != null) {\r
119             val templateContent = bluePrintRuntimeService.resolveNodeTemplateArtifact(nodeTemplateName, artifactTemplate)\r
120             resolvedContent = BluePrintTemplateService.generateContent(templateContent, resolvedParamJsonContent)\r
121         } else {\r
122             resolvedContent = resolvedParamJsonContent\r
123         }\r
124         return resolvedContent\r
125     }\r
126 \r
127     /**\r
128      * Iterate the Batch, get the Resource Assignment, dictionary Name, Look for the Resource definition for the\r
129      * name, then get the type of the Resource Definition, Get the instance for the Resource Type and process the\r
130      * request.\r
131      */\r
132     override fun resolveResourceAssignments(blueprintRuntimeService: BluePrintRuntimeService<*>,\r
133                                             resourceDictionaries: MutableMap<String, ResourceDefinition>,\r
134                                             resourceAssignments: MutableList<ResourceAssignment>,\r
135                                             identifierName: String) {\r
136 \r
137         val bulkSequenced = BulkResourceSequencingUtils.process(resourceAssignments)\r
138         val resourceAssignmentRuntimeService = ResourceAssignmentUtils.transformToRARuntimeService(blueprintRuntimeService, identifierName)\r
139 \r
140         bulkSequenced.map { batchResourceAssignments ->\r
141             batchResourceAssignments.filter { it.name != "*" && it.name != "start" }\r
142                     .forEach { resourceAssignment ->\r
143                         val dictionaryName = resourceAssignment.dictionaryName\r
144                         val dictionarySource = resourceAssignment.dictionarySource\r
145                         /**\r
146                          * Get the Processor name\r
147                          */\r
148                         val processorName = processorName(dictionaryName!!, dictionarySource!!,\r
149                                 resourceDictionaries)\r
150 \r
151                         val resourceAssignmentProcessor = applicationContext.getBean(processorName) as? ResourceAssignmentProcessor\r
152                                 ?: throw BluePrintProcessorException("failed to get resource processor for name($processorName) " +\r
153                                         "for resource assignment(${resourceAssignment.name})")\r
154                         try {\r
155                             // Set BluePrint Runtime Service\r
156                             resourceAssignmentProcessor.raRuntimeService = resourceAssignmentRuntimeService\r
157                             // Set Resource Dictionaries\r
158                             resourceAssignmentProcessor.resourceDictionaries = resourceDictionaries\r
159                             // Invoke Apply Method\r
160                             resourceAssignmentProcessor.apply(resourceAssignment)\r
161                         } catch (e: RuntimeException) {\r
162                             resourceAssignmentProcessor.recover(e, resourceAssignment)\r
163                             throw BluePrintProcessorException(e)\r
164                         }\r
165                     }\r
166         }\r
167     }\r
168 \r
169 \r
170     /**\r
171      * If the Source instance is "input", then it is not mandatory to have source Resource Definition, So it can\r
172      *  derive the default input processor.\r
173      */\r
174     private fun processorName(dictionaryName: String, dictionarySource: String,\r
175                               resourceDictionaries: MutableMap<String, ResourceDefinition>): String {\r
176         var processorName: String? = null\r
177         when (dictionarySource) {\r
178             "input" -> {\r
179                 processorName = "${ResourceResolutionConstants.PREFIX_RESOURCE_RESOLUTION_PROCESSOR}source-input"\r
180             }\r
181             "default" -> {\r
182                 processorName = "${ResourceResolutionConstants.PREFIX_RESOURCE_RESOLUTION_PROCESSOR}source-default"\r
183             }\r
184             else -> {\r
185                 val resourceDefinition = resourceDictionaries[dictionaryName]\r
186                         ?: throw BluePrintProcessorException("couldn't get resource dictionary definition for $dictionaryName")\r
187 \r
188                 val resourceSource = resourceDefinition.sources[dictionarySource]\r
189                         ?: throw BluePrintProcessorException("couldn't get resource definition $dictionaryName source($dictionarySource)")\r
190 \r
191                 processorName = ResourceResolutionConstants.PREFIX_RESOURCE_RESOLUTION_PROCESSOR\r
192                         .plus(resourceSource.type)\r
193             }\r
194         }\r
195         checkNotEmptyOrThrow(processorName,\r
196                 "couldn't get processor name for resource dictionary definition($dictionaryName) source" +\r
197                         "($dictionarySource)")\r
198 \r
199         return processorName\r
200 \r
201     }\r
202 }\r