Merge "Remote Python executor unescapes script parameter values"
[ccsdk/cds.git] / ms / blueprintsprocessor / functions / python-executor / src / test / kotlin / org / onap / ccsdk / cds / blueprintsprocessor / functions / python / executor / ComponentRemotePythonExecutorTest.kt
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.functions.python.executor
18
19 import com.fasterxml.jackson.databind.JsonNode
20 import com.fasterxml.jackson.databind.ObjectMapper
21 import io.mockk.every
22 import io.mockk.mockk
23 import kotlinx.coroutines.runBlocking
24 import org.junit.Test
25 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput
26 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.PrepareRemoteEnvInput
27 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.RemoteScriptExecutionInput
28 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.RemoteScriptExecutionOutput
29 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.StatusType
30 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.StepData
31 import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.RemoteScriptExecutionService
32 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
33 import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive
34 import org.onap.ccsdk.cds.controllerblueprints.core.putJsonElement
35 import org.onap.ccsdk.cds.controllerblueprints.core.service.DefaultBluePrintRuntimeService
36 import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintMetadataUtils
37 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
38 import kotlin.test.assertEquals
39 import kotlin.test.assertNotNull
40
41
42 class ComponentRemotePythonExecutorTest {
43
44     @Test
45     fun testComponentRemotePythonExecutor() {
46         runBlocking {
47             val remoteScriptExecutionService = MockRemoteScriptExecutionService()
48
49             val componentRemotePythonExecutor = ComponentRemotePythonExecutor(remoteScriptExecutionService)
50
51             val executionServiceInput = JacksonUtils.readValueFromClassPathFile("payload/requests/sample-activate-request.json",
52                     ExecutionServiceInput::class.java)!!
53
54             val bluePrintRuntimeService = BluePrintMetadataUtils.getBluePrintRuntime("123456-1000",
55                     "./../../../../components/model-catalog/blueprint-model/test-blueprint/remote_scripts")
56
57             val stepMetaData: MutableMap<String, JsonNode> = hashMapOf()
58             stepMetaData.putJsonElement(BluePrintConstants.PROPERTY_CURRENT_NODE_TEMPLATE, "execute-remote-python")
59             stepMetaData.putJsonElement(BluePrintConstants.PROPERTY_CURRENT_INTERFACE, "ComponentRemotePythonExecutor")
60             stepMetaData.putJsonElement(BluePrintConstants.PROPERTY_CURRENT_OPERATION, "process")
61             componentRemotePythonExecutor.bluePrintRuntimeService = bluePrintRuntimeService
62             val stepInputData = StepData().apply {
63                 name = "execute-remote-python"
64                 properties = stepMetaData
65             }
66             executionServiceInput.stepData = stepInputData
67             componentRemotePythonExecutor.applyNB(executionServiceInput)
68         }
69     }
70
71     /**
72      * Test cases for python executor to work with the process NB of remote
73      * executor.
74      */
75     @Test
76     fun testComponentRemotePythonExecutorProcessNB() {
77         runBlocking {
78             val remoteScriptExecutionService =
79                     MockRemoteScriptExecutionService()
80             val componentRemotePythonExecutor = ComponentRemotePythonExecutor(
81                     remoteScriptExecutionService)
82             val bluePrintRuntime = mockk<DefaultBluePrintRuntimeService>(
83                     "123456-1000")
84             val input  = getMockedOutput(bluePrintRuntime)
85             componentRemotePythonExecutor.bluePrintRuntimeService =
86                     bluePrintRuntime
87             componentRemotePythonExecutor.applyNB(input)
88         }
89     }
90
91     /**
92      * Mocked input information for remote python executor.
93      */
94     fun getMockedOutput(svc: DefaultBluePrintRuntimeService):
95             ExecutionServiceInput {
96         val stepMetaData: MutableMap<String, JsonNode> = hashMapOf()
97
98         stepMetaData.putJsonElement(
99                 BluePrintConstants.PROPERTY_CURRENT_NODE_TEMPLATE,
100                 "execute-remote-python")
101         stepMetaData.putJsonElement(
102                 BluePrintConstants.PROPERTY_CURRENT_INTERFACE,
103                 "ComponentRemotePythonExecutor")
104         stepMetaData.putJsonElement(
105                 BluePrintConstants.PROPERTY_CURRENT_OPERATION, "process")
106
107         val mapper = ObjectMapper()
108         val rootNode = mapper.createObjectNode()
109         rootNode.put("ip-address", "0.0.0.0")
110         rootNode.put("type", "rest")
111
112         val operationalInputs: MutableMap<String, JsonNode> = hashMapOf()
113         operationalInputs.putJsonElement(
114                 BluePrintConstants.PROPERTY_CURRENT_NODE_TEMPLATE,
115                 "execute-remote-python")
116         operationalInputs.putJsonElement(
117                 BluePrintConstants.PROPERTY_CURRENT_INTERFACE,
118                 "ComponentRemotePythonExecutor")
119         operationalInputs.putJsonElement(
120                 BluePrintConstants.PROPERTY_CURRENT_OPERATION, "process")
121         operationalInputs.putJsonElement("endpoint-selector", "aai")
122         operationalInputs.putJsonElement("dynamic-properties", rootNode)
123         operationalInputs.putJsonElement("command", "./run.sh")
124         operationalInputs.putJsonElement("packages", "py")
125
126         every {
127             svc.resolveNodeTemplateInterfaceOperationInputs(
128                     "execute-remote-python",
129                     "ComponentRemotePythonExecutor", "process")
130         } returns operationalInputs
131
132         val stepInputData = StepData().apply {
133             name = "execute-remote-python"
134             properties = stepMetaData
135         }
136
137         val executionServiceInput = JacksonUtils
138                 .readValueFromClassPathFile(
139                         "payload/requests/sample-remote-python-request.json",
140                         ExecutionServiceInput::class.java)!!
141         executionServiceInput.stepData = stepInputData
142
143         val operationOutputs = hashMapOf<String, JsonNode>()
144         every {
145             svc.resolveNodeTemplateInterfaceOperationOutputs(
146                     "execute-remote-python",
147                     "ComponentRemotePythonExecutor", "process")
148         } returns operationOutputs
149         val bluePrintRuntimeService = BluePrintMetadataUtils
150                 .getBluePrintRuntime("123456-1000",
151                         "./../../../../components/model-" +
152                                 "catalog/blueprint-model/test-blueprint/" +
153                                 "remote_scripts")
154         every {
155             svc.resolveNodeTemplateArtifactDefinition(
156                     "execute-remote-python", "component-script")
157         } returns bluePrintRuntimeService.resolveNodeTemplateArtifactDefinition(
158                 "execute-remote-python", "component-script")
159         every {
160             svc.setNodeTemplateAttributeValue(
161                     "execute-remote-python", "prepare-environment-logs",
162                     "prepared successfully".asJsonPrimitive())
163         } returns Unit
164         every {
165             svc.setNodeTemplateAttributeValue(
166                     "execute-remote-python",
167                     "execute-command-logs", "N/A".asJsonPrimitive())
168         } returns Unit
169         every {
170             svc.setNodeTemplateAttributeValue(
171                     "execute-remote-python",
172                     "execute-command-logs",
173                     "processed successfully".asJsonPrimitive())
174         } returns Unit
175
176         every {
177             svc.bluePrintContext()
178         } returns bluePrintRuntimeService.bluePrintContext()
179         return executionServiceInput
180     }
181 }
182
183 class MockRemoteScriptExecutionService : RemoteScriptExecutionService {
184     override suspend fun init(selector: String) {
185     }
186
187     override suspend fun prepareEnv(prepareEnvInput: PrepareRemoteEnvInput): RemoteScriptExecutionOutput {
188         assertEquals(prepareEnvInput.requestId, "123456-1000", "failed to match request id")
189         assertNotNull(prepareEnvInput.packages, "failed to get packages")
190
191         val remoteScriptExecutionOutput = mockk<RemoteScriptExecutionOutput>()
192         every { remoteScriptExecutionOutput.response } returns listOf("prepared successfully")
193         every { remoteScriptExecutionOutput.status } returns StatusType.SUCCESS
194         return remoteScriptExecutionOutput
195     }
196
197     override suspend fun executeCommand(remoteExecutionInput: RemoteScriptExecutionInput): RemoteScriptExecutionOutput {
198         assertEquals(remoteExecutionInput.requestId, "123456-1000", "failed to match request id")
199
200         val remoteScriptExecutionOutput = mockk<RemoteScriptExecutionOutput>()
201         every { remoteScriptExecutionOutput.response } returns listOf("processed successfully")
202         every { remoteScriptExecutionOutput.status } returns StatusType.SUCCESS
203         return remoteScriptExecutionOutput
204     }
205
206     override suspend fun close() {
207
208     }
209 }