95b2afc4c40640e1ce04bff88a89f9193c16b5e7
[ccsdk/cds.git] /
1 /*
2  *  Copyright © 2019 IBM.
3  *
4  *  Licensed under the Apache License, Version 2.0 (the "License");
5  *  you may not use this file except in compliance with the License.
6  *  You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *  Unless required by applicable law or agreed to in writing, software
11  *  distributed under the License is distributed on an "AS IS" BASIS,
12  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *  See the License for the specific language governing permissions and
14  *  limitations under the License.
15  */
16
17 package org.onap.ccsdk.cds.blueprintsprocessor.services.execution
18
19 import com.fasterxml.jackson.databind.JsonNode
20 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput
21 import org.onap.ccsdk.cds.controllerblueprints.core.*
22 import org.onap.ccsdk.cds.controllerblueprints.core.data.ArtifactDefinition
23 import org.onap.ccsdk.cds.controllerblueprints.core.data.Implementation
24 import org.onap.ccsdk.cds.controllerblueprints.core.data.NodeTemplate
25 import org.onap.ccsdk.cds.controllerblueprints.core.data.NodeType
26 import org.onap.ccsdk.cds.controllerblueprints.core.dsl.ArtifactDefinitionBuilder
27 import org.onap.ccsdk.cds.controllerblueprints.core.dsl.nodeTemplate
28 import org.onap.ccsdk.cds.controllerblueprints.core.dsl.nodeType
29 import org.springframework.beans.factory.config.ConfigurableBeanFactory
30 import org.springframework.context.annotation.Scope
31 import org.springframework.stereotype.Component
32
33 /**
34  * This is generic Script Component Executor function
35  * @author Brinda Santh
36  */
37 @Component("component-script-executor")
38 @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
39 open class ComponentScriptExecutor(private var componentFunctionScriptingService: ComponentFunctionScriptingService)
40     : AbstractComponentFunction() {
41
42     companion object {
43         const val SCRIPT_TYPE = "script-type"
44         const val SCRIPT_CLASS_REFERENCE = "script-class-reference"
45         const val DYNAMIC_PROPERTIES = "dynamic-properties"
46         const val RESPONSE_DATA = "response-data"
47         const val STATUS = "status"
48     }
49
50     lateinit var scriptComponentFunction: AbstractScriptComponentFunction
51
52     override suspend fun processNB(executionRequest: ExecutionServiceInput) {
53
54         val scriptType = operationInputs.getAsString(SCRIPT_TYPE)
55         val scriptClassReference = operationInputs.getAsString(SCRIPT_CLASS_REFERENCE)
56
57         val scriptDependencies: MutableList<String> = arrayListOf()
58         populateScriptDependencies(scriptDependencies)
59
60         scriptComponentFunction = componentFunctionScriptingService.scriptInstance(this, scriptType,
61                 scriptClassReference, scriptDependencies)
62
63         // Handles both script processing and error handling
64         scriptComponentFunction.executeScript(executionServiceInput)
65     }
66
67     override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) {
68         bluePrintRuntimeService.getBluePrintError()
69                 .addError("Failed in ComponentCliExecutor : ${runtimeException.message}")
70
71     }
72
73     open fun populateScriptDependencies(scriptDependencies: MutableList<String>) {
74         /** Place holder for Child to add extra dependencies */
75     }
76 }
77
78 /** Component Extensions **/
79
80 fun BluePrintTypes.componentScriptExecutor(): NodeType {
81     return nodeType(id = "component-script-executor", version = BluePrintConstants.DEFAULT_VERSION_NUMBER,
82             derivedFrom = BluePrintConstants.MODEL_TYPE_NODE_COMPONENT,
83             description = "Generic Script Component Executor") {
84         attribute(ComponentScriptExecutor.RESPONSE_DATA, BluePrintConstants.DATA_TYPE_JSON, false)
85         attribute(ComponentScriptExecutor.STATUS, BluePrintConstants.DATA_TYPE_STRING, true)
86
87         operation("ComponentScriptExecutor", "ComponentScriptExecutor Operation") {
88             inputs {
89                 property(ComponentScriptExecutor.SCRIPT_TYPE, BluePrintConstants.DATA_TYPE_STRING, true,
90                         "Script Type") {
91                     defaultValue(BluePrintConstants.SCRIPT_INTERNAL)
92                     constrain {
93                         validValues(listOf(BluePrintConstants.SCRIPT_INTERNAL.asJsonPrimitive(),
94                                 BluePrintConstants.SCRIPT_JYTHON.asJsonPrimitive(),
95                                 BluePrintConstants.SCRIPT_KOTLIN.asJsonPrimitive()))
96                     }
97                 }
98                 property(ComponentScriptExecutor.SCRIPT_CLASS_REFERENCE, BluePrintConstants.DATA_TYPE_STRING,
99                         true, "Kotlin Script class name or jython script name.")
100                 property(ComponentScriptExecutor.DYNAMIC_PROPERTIES, BluePrintConstants.DATA_TYPE_JSON, false,
101                         "Dynamic Json Content or DSL Json reference.")
102             }
103             outputs {
104                 property(ComponentScriptExecutor.RESPONSE_DATA, BluePrintConstants.DATA_TYPE_JSON, false,
105                         "Output Response")
106                 property(ComponentScriptExecutor.STATUS, BluePrintConstants.DATA_TYPE_STRING, true,
107                         "Status of the Component Execution ( success or failure )")
108             }
109         }
110     }
111 }
112
113 /** Component Builder */
114
115 fun componentScriptExecutor(id: String, description: String,
116                             block: ComponentScriptExecutorBuilder.() -> Unit): NodeTemplate {
117     return ComponentScriptExecutorBuilder(id, description).apply(block).build()
118 }
119
120 class ComponentScriptExecutorBuilder(private val id: String, private val description: String) {
121     private var implementation: Implementation? = null
122     private var inputs: MutableMap<String, JsonNode>? = null
123     private var outputs: MutableMap<String, JsonNode>? = null
124     private var artifacts: MutableMap<String, ArtifactDefinition>? = null
125
126     fun implementation(timeout: Int, operationHost: String? = BluePrintConstants.PROPERTY_SELF) {
127         val implementation = Implementation().apply {
128             this.operationHost = operationHost!!
129             this.timeout = timeout
130         }
131         this.implementation = implementation
132     }
133
134     fun inputs(block: InputAssignmentBuilder.() -> Unit) {
135         this.inputs = InputAssignmentBuilder().apply(block).build()
136     }
137
138     fun outputs(block: OutputAssignmentBuilder.() -> Unit) {
139         this.outputs = OutputAssignmentBuilder().apply(block).build()
140     }
141
142     fun artifact(id: String, type: String, file: String) {
143         if (artifacts == null)
144             artifacts = hashMapOf()
145         artifacts!![id] = ArtifactDefinitionBuilder(id, type, file).build()
146     }
147
148     fun artifact(id: String, type: String, file: String, block: ArtifactDefinitionBuilder.() -> Unit) {
149         if (artifacts == null)
150             artifacts = hashMapOf()
151         artifacts!![id] = ArtifactDefinitionBuilder(id, type, file).apply(block).build()
152     }
153
154     fun build(): NodeTemplate {
155         return nodeTemplate(id, "component-script-executor", description) {
156             operation("ComponentScriptExecutor") {
157                 implementation(implementation)
158                 inputs(inputs)
159                 outputs(outputs)
160             }
161             artifacts(artifacts)
162         }
163     }
164
165     class InputAssignmentBuilder {
166         val properties: MutableMap<String, JsonNode> = hashMapOf()
167
168         fun type(type: String) {
169             properties[ComponentScriptExecutor.SCRIPT_TYPE] = type.asJsonPrimitive()
170         }
171
172         fun scriptClassReference(scriptClassReference: String) {
173             properties[ComponentScriptExecutor.SCRIPT_CLASS_REFERENCE] = scriptClassReference.asJsonPrimitive()
174         }
175
176         fun dynamicProperty(dynamicProperty: Any) {
177             dynamicProperty(dynamicProperty.asJsonType())
178         }
179
180         fun dynamicProperty(dynamicProperty: JsonNode) {
181             properties[ComponentScriptExecutor.DYNAMIC_PROPERTIES] = dynamicProperty
182         }
183
184         fun build(): MutableMap<String, JsonNode> {
185             return properties
186         }
187     }
188
189     class OutputAssignmentBuilder {
190         val properties: MutableMap<String, JsonNode> = hashMapOf()
191
192         fun status(status: String) {
193             properties[ComponentScriptExecutor.STATUS] = status.asJsonPrimitive()
194         }
195
196         fun responseData(responseData: Any) {
197             responseData(responseData.asJsonType())
198         }
199
200         fun responseData(responseData: JsonNode) {
201             properties[ComponentScriptExecutor.RESPONSE_DATA] = responseData
202         }
203
204         fun build(): MutableMap<String, JsonNode> {
205             return properties
206         }
207     }
208 }