aboutsummaryrefslogtreecommitdiffstats
path: root/ms/blueprintsprocessor/functions/ansible-awx-executor/src
diff options
context:
space:
mode:
Diffstat (limited to 'ms/blueprintsprocessor/functions/ansible-awx-executor/src')
-rw-r--r--ms/blueprintsprocessor/functions/ansible-awx-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/ansible/executor/ComponentRemoteAnsibleExecutor.kt89
-rw-r--r--ms/blueprintsprocessor/functions/ansible-awx-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/ansible/executor/ComponentRemoteAnsibleExecutorTest.kt52
2 files changed, 88 insertions, 53 deletions
diff --git a/ms/blueprintsprocessor/functions/ansible-awx-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/ansible/executor/ComponentRemoteAnsibleExecutor.kt b/ms/blueprintsprocessor/functions/ansible-awx-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/ansible/executor/ComponentRemoteAnsibleExecutor.kt
index 3a655ded7..9ea6034a8 100644
--- a/ms/blueprintsprocessor/functions/ansible-awx-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/ansible/executor/ComponentRemoteAnsibleExecutor.kt
+++ b/ms/blueprintsprocessor/functions/ansible-awx-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/ansible/executor/ComponentRemoteAnsibleExecutor.kt
@@ -24,7 +24,12 @@ import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInpu
import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.BluePrintRestLibPropertyService
import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.BlueprintWebClientService
import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractComponentFunction
-import org.onap.ccsdk.cds.controllerblueprints.core.*
+import org.onap.ccsdk.cds.controllerblueprints.core.asJsonNode
+import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive
+import org.onap.ccsdk.cds.controllerblueprints.core.asJsonString
+import org.onap.ccsdk.cds.controllerblueprints.core.isNullOrMissing
+import org.onap.ccsdk.cds.controllerblueprints.core.returnNullIfMissing
+import org.onap.ccsdk.cds.controllerblueprints.core.rootFieldsToMap
import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.config.ConfigurableBeanFactory
@@ -33,7 +38,7 @@ import org.springframework.http.HttpMethod
import org.springframework.stereotype.Component
import java.net.URI
import java.net.URLEncoder
-import java.util.*
+import java.util.NoSuchElementException
/**
* ComponentRemoteAnsibleExecutor
@@ -48,9 +53,11 @@ import java.util.*
*/
@Component("component-remote-ansible-executor")
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
-open class ComponentRemoteAnsibleExecutor(private val blueprintRestLibPropertyService: BluePrintRestLibPropertyService,
- private val mapper: ObjectMapper)
- : AbstractComponentFunction() {
+open class ComponentRemoteAnsibleExecutor(
+ private val blueprintRestLibPropertyService: BluePrintRestLibPropertyService,
+ private val mapper: ObjectMapper
+) :
+ AbstractComponentFunction() {
// HTTP related constants
private val HTTP_SUCCESS = 200..202
@@ -98,7 +105,7 @@ open class ComponentRemoteAnsibleExecutor(private val blueprintRestLibPropertySe
if (jtId.isNotEmpty()) {
runJobTemplateOnAWX(restClientService, jobTemplateName, jtId, workflowURIPrefix)
} else {
- val message = "Workflow/Job template ${jobTemplateName} does not exists"
+ val message = "Workflow/Job template $jobTemplateName does not exists"
log.error(message)
setNodeOutputErrors(ATTRIBUTE_EXEC_CMD_STATUS_ERROR, message)
}
@@ -108,7 +115,6 @@ open class ComponentRemoteAnsibleExecutor(private val blueprintRestLibPropertySe
}
}
-
override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) {
val message = "Error in ComponentRemoteAnsibleExecutor : ${runtimeException.message}"
log.error(message, runtimeException)
@@ -143,11 +149,16 @@ open class ComponentRemoteAnsibleExecutor(private val blueprintRestLibPropertySe
/**
* Finds the job template ID based on the job template name provided in the request
*/
- private fun lookupJobTemplateIDByName(awxClient: BlueprintWebClientService, job_template_name: String?,
- workflowPrefix : String) : String {
- val encodedJTName = URI(null, null,
- "/api/v2/${workflowPrefix}job_templates/${job_template_name}/",
- null, null).rawPath
+ private fun lookupJobTemplateIDByName(
+ awxClient: BlueprintWebClientService,
+ job_template_name: String?,
+ workflowPrefix: String
+ ): String {
+ val encodedJTName = URI(
+ null, null,
+ "/api/v2/${workflowPrefix}job_templates/$job_template_name/",
+ null, null
+ ).rawPath
// Get Job Template details by name
var response = awxClient.exchangeResource(GET, encodedJTName, "")
@@ -161,12 +172,16 @@ open class ComponentRemoteAnsibleExecutor(private val blueprintRestLibPropertySe
* its execution. Finally, it retrieves the job results via the stdout api.
* The status and output attributes are populated in the process.
*/
- private fun runJobTemplateOnAWX(awxClient: BlueprintWebClientService, job_template_name: String?, jtId: String,
- workflowPrefix : String) {
- setNodeOutputProperties("preparing".asJsonPrimitive(), "".asJsonPrimitive(), "".asJsonPrimitive())
+ private fun runJobTemplateOnAWX(
+ awxClient: BlueprintWebClientService,
+ job_template_name: String?,
+ jtId: String,
+ workflowPrefix: String
+ ) {
+ setNodeOutputProperties("preparing".asJsonPrimitive(), "".asJsonPrimitive(), "".asJsonPrimitive())
// Get Job Template requirements
- var response = awxClient.exchangeResource(GET, "/api/v2/${workflowPrefix}job_templates/${jtId}/launch/", "")
+ var response = awxClient.exchangeResource(GET, "/api/v2/${workflowPrefix}job_templates/$jtId/launch/", "")
// FIXME: handle non-successful SC
val jtLaunchReqs: JsonNode = mapper.readTree(response.body)
val payload = prepareLaunchPayload(awxClient, jtLaunchReqs, workflowPrefix.isNotBlank())
@@ -175,7 +190,7 @@ open class ComponentRemoteAnsibleExecutor(private val blueprintRestLibPropertySe
// Launch the job for the targeted template
var jtLaunched: JsonNode = JacksonUtils.objectMapper.createObjectNode()
- response = awxClient.exchangeResource(POST, "/api/v2/${workflowPrefix}job_templates/${jtId}/launch/", payload)
+ response = awxClient.exchangeResource(POST, "/api/v2/${workflowPrefix}job_templates/$jtId/launch/", payload)
if (response.status in HTTP_SUCCESS) {
jtLaunched = mapper.readTree(response.body)
val fieldsIgnored: JsonNode = jtLaunched.at("/ignored_fields")
@@ -191,7 +206,7 @@ open class ComponentRemoteAnsibleExecutor(private val blueprintRestLibPropertySe
var jobStatus = "unknown"
var jobEndTime = "null"
while (jobEndTime == "null") {
- response = awxClient.exchangeResource(GET, "/api/v2/${workflowPrefix}jobs/${jobId}/", "")
+ response = awxClient.exchangeResource(GET, "/api/v2/${workflowPrefix}jobs/$jobId/", "")
val jobLaunched: JsonNode = mapper.readTree(response.body)
jobStatus = jobLaunched.at("/status").asText()
jobEndTime = jobLaunched.at("/finished").asText()
@@ -201,7 +216,6 @@ open class ComponentRemoteAnsibleExecutor(private val blueprintRestLibPropertySe
log.info("Execution of job template $job_template_name in job #$jobId finished with status ($jobStatus) for requestId $processId")
populateJobRunResponse(awxClient, jobId, workflowPrefix, jobStatus)
-
} else {
// The job template requirements were not fulfilled with the values passed in. The message below will
// provide more information via the response, like the ignored_fields, or variables_needed_to_start,
@@ -217,8 +231,12 @@ open class ComponentRemoteAnsibleExecutor(private val blueprintRestLibPropertySe
* Extracts the output from either a job stdout call OR collects the workflow run output, as well as the artifacts
* and populate the component corresponding output properties
*/
- private fun populateJobRunResponse(awxClient: BlueprintWebClientService, jobId: String, workflowPrefix: String,
- jobStatus: String) {
+ private fun populateJobRunResponse(
+ awxClient: BlueprintWebClientService,
+ jobId: String,
+ workflowPrefix: String,
+ jobStatus: String
+ ) {
val collectedResponses = StringBuilder(4096)
val artifacts: MutableMap<String, JsonNode> = mutableMapOf()
@@ -226,20 +244,20 @@ open class ComponentRemoteAnsibleExecutor(private val blueprintRestLibPropertySe
collectJobIdsRelatedToJobRun(awxClient, jobId, workflowPrefix).forEach { aJobId ->
// Collect the response text from the corresponding jobIds
- var response = awxClient.exchangeResource(GET, "/api/v2/jobs/${aJobId}/stdout/?format=txt", "", plainTextHeaders)
+ var response = awxClient.exchangeResource(GET, "/api/v2/jobs/$aJobId/stdout/?format=txt", "", plainTextHeaders)
if (response.status in HTTP_SUCCESS) {
val jobOutput = response.body
collectedResponses
- .append("Output for Job $aJobId :" + System.lineSeparator())
- .append(jobOutput)
- .append(System.lineSeparator())
- log.info("Response for job ${aJobId}: \n ${jobOutput} \n")
+ .append("Output for Job $aJobId :" + System.lineSeparator())
+ .append(jobOutput)
+ .append(System.lineSeparator())
+ log.info("Response for job $aJobId: \n $jobOutput \n")
} else {
- log.warn("Could not gather response for job ${aJobId}. Status=${response.status}")
+ log.warn("Could not gather response for job $aJobId. Status=${response.status}")
}
// Collect artifacts variables from each job and gather them up in one json node
- response = awxClient.exchangeResource(GET, "/api/v2/jobs/${aJobId}/", "")
+ response = awxClient.exchangeResource(GET, "/api/v2/jobs/$aJobId/", "")
if (response.status in HTTP_SUCCESS) {
val jobArtifacts = mapper.readTree(response.body).at("/artifacts")
if (jobArtifacts != null) {
@@ -248,7 +266,7 @@ open class ComponentRemoteAnsibleExecutor(private val blueprintRestLibPropertySe
}
}
- log.info("Artifacts for job ${jobId}: \n $artifacts \n")
+ log.info("Artifacts for job $jobId: \n $artifacts \n")
setNodeOutputProperties(jobStatus.asJsonPrimitive(), collectedResponses.toString().asJsonPrimitive(), artifacts.asJsonNode())
}
@@ -261,7 +279,7 @@ open class ComponentRemoteAnsibleExecutor(private val blueprintRestLibPropertySe
var jobIds: Array<String>
if (workflowPrefix.isNotEmpty()) {
- var response = awxClient.exchangeResource(GET, "/api/v2/${workflowPrefix}jobs/${jobId}/workflow_nodes/", "")
+ var response = awxClient.exchangeResource(GET, "/api/v2/${workflowPrefix}jobs/$jobId/workflow_nodes/", "")
val jobDetails = mapper.readTree(response.body).at("/results")
// gather up job Id of all actual job nodes that ran during the workflow
@@ -282,8 +300,11 @@ open class ComponentRemoteAnsibleExecutor(private val blueprintRestLibPropertySe
* by applying the overrides that were provided
* and allowed by the template definition flags in jtLaunchReqs
*/
- private fun prepareLaunchPayload(awxClient: BlueprintWebClientService, jtLaunchReqs: JsonNode,
- isWorkflow : Boolean): String {
+ private fun prepareLaunchPayload(
+ awxClient: BlueprintWebClientService,
+ jtLaunchReqs: JsonNode,
+ isWorkflow: Boolean
+ ): String {
val payload = JacksonUtils.objectMapper.createObjectNode()
// Parameter defaults
@@ -318,7 +339,7 @@ open class ComponentRemoteAnsibleExecutor(private val blueprintRestLibPropertySe
payload.set(INPUT_INVENTORY, inventoryKeyId)
}
- payload.set("extra_vars", extraArgs)
+ payload.set("extra_vars", extraArgs)
return payload.asJsonString(false)
}
@@ -363,7 +384,7 @@ open class ComponentRemoteAnsibleExecutor(private val blueprintRestLibPropertySe
/**
* Utility function to set the output properties and errors of the executor node, in cas of errors
*/
- private fun setNodeOutputErrors(status: String, message: String, artifacts: JsonNode = "".asJsonPrimitive() ) {
+ private fun setNodeOutputErrors(status: String, message: String, artifacts: JsonNode = "".asJsonPrimitive()) {
setAttribute(ATTRIBUTE_EXEC_CMD_STATUS, status.asJsonPrimitive())
setAttribute(ATTRIBUTE_EXEC_CMD_LOG, message.asJsonPrimitive())
setAttribute(ATTRIBUTE_EXEC_CMD_ARTIFACTS, artifacts)
diff --git a/ms/blueprintsprocessor/functions/ansible-awx-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/ansible/executor/ComponentRemoteAnsibleExecutorTest.kt b/ms/blueprintsprocessor/functions/ansible-awx-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/ansible/executor/ComponentRemoteAnsibleExecutorTest.kt
index 5e0905dec..262563d1f 100644
--- a/ms/blueprintsprocessor/functions/ansible-awx-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/ansible/executor/ComponentRemoteAnsibleExecutorTest.kt
+++ b/ms/blueprintsprocessor/functions/ansible-awx-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/ansible/executor/ComponentRemoteAnsibleExecutorTest.kt
@@ -73,20 +73,24 @@ class ComponentRemoteAnsibleExecutorTest {
webClientService.exchangeResource("GET", "/api/v2/inventories/?name=Demo+Inventory", "")
} returns WebClientResponse(200, getInventory())
every {
- webClientService.exchangeResource("POST", "/api/v2/job_templates/$jtId/launch/",
- """{"inventory":1,"extra_vars":{"site_id":"3 - Belmont","tor_group":"vEPC"}}""")
+ webClientService.exchangeResource(
+ "POST", "/api/v2/job_templates/$jtId/launch/",
+ """{"inventory":1,"extra_vars":{"site_id":"3 - Belmont","tor_group":"vEPC"}}"""
+ )
} returns WebClientResponse(201, newJobTemplateLaunch(jtId, jobId))
every {
webClientService.exchangeResource("GET", "/api/v2/jobs/$jobId/", "")
} returnsMany listOf(
- WebClientResponse(200, getJobStatus1(jtId, jobId)),
- WebClientResponse(200, getJobStatus2(jtId, jobId)),
- WebClientResponse(200, getJobStatus3(jtId, jobId)),
- WebClientResponse(200, getJobStatus4(jtId, jobId))
+ WebClientResponse(200, getJobStatus1(jtId, jobId)),
+ WebClientResponse(200, getJobStatus2(jtId, jobId)),
+ WebClientResponse(200, getJobStatus3(jtId, jobId)),
+ WebClientResponse(200, getJobStatus4(jtId, jobId))
)
every {
- webClientService.exchangeResource("GET", "/api/v2/jobs/$jobId/stdout/?format=txt", "",
- mapOf("Accept" to "text/plain"))
+ webClientService.exchangeResource(
+ "GET", "/api/v2/jobs/$jobId/stdout/?format=txt", "",
+ mapOf("Accept" to "text/plain")
+ )
} returns WebClientResponse(200, getReport())
val selector = mapper.readTree(endpointSelector)
val bluePrintRestLibPropertyService = mockk<BluePrintRestLibPropertyService>()
@@ -95,8 +99,9 @@ class ComponentRemoteAnsibleExecutorTest {
awxRemoteExecutor.checkDelay = 1
val executionServiceInput = JacksonUtils.readValueFromClassPathFile(
- "payload/requests/sample-remote-ansible-request.json",
- ExecutionServiceInput::class.java)!!
+ "payload/requests/sample-remote-ansible-request.json",
+ ExecutionServiceInput::class.java
+ )!!
val bluePrintRuntimeService = createBlueprintRuntimeService(awxRemoteExecutor, executionServiceInput)
@@ -128,8 +133,9 @@ class ComponentRemoteAnsibleExecutorTest {
awxRemoteExecutor.checkDelay = 1
val executionServiceInput = JacksonUtils.readValueFromClassPathFile(
- "payload/requests/remote-ansible-request-full.json",
- ExecutionServiceInput::class.java)!!
+ "payload/requests/remote-ansible-request-full.json",
+ ExecutionServiceInput::class.java
+ )!!
val bluePrintRuntimeService = createBlueprintRuntimeService(awxRemoteExecutor, executionServiceInput)
@@ -156,8 +162,10 @@ class ComponentRemoteAnsibleExecutorTest {
webClientService.exchangeResource("GET", "/api/v2/inventories/?name=Demo+Inventory", "")
} returns WebClientResponse(200, getInventory())
every {
- webClientService.exchangeResource("POST", "/api/v2/job_templates/$jtId/launch/",
- """{"limit":"123","tags":"some-tag","skip_tags":"some-skip-tag","inventory":1,"extra_vars":{"site_id":"3 - Belmont","tor_group":"vEPC"}}""")
+ webClientService.exchangeResource(
+ "POST", "/api/v2/job_templates/$jtId/launch/",
+ """{"limit":"123","tags":"some-tag","skip_tags":"some-skip-tag","inventory":1,"extra_vars":{"site_id":"3 - Belmont","tor_group":"vEPC"}}"""
+ )
} returns WebClientResponse(500, "")
val selector = mapper.readTree(endpointSelector)
val bluePrintRestLibPropertyService = mockk<BluePrintRestLibPropertyService>()
@@ -166,8 +174,9 @@ class ComponentRemoteAnsibleExecutorTest {
awxRemoteExecutor.checkDelay = 1
val executionServiceInput = JacksonUtils.readValueFromClassPathFile(
- "payload/requests/remote-ansible-request-full.json",
- ExecutionServiceInput::class.java)!!
+ "payload/requests/remote-ansible-request-full.json",
+ ExecutionServiceInput::class.java
+ )!!
val bluePrintRuntimeService = createBlueprintRuntimeService(awxRemoteExecutor, executionServiceInput)
@@ -181,9 +190,14 @@ class ComponentRemoteAnsibleExecutorTest {
assertEquals(1, errors.size)
}
- private fun createBlueprintRuntimeService(awxRemoteExecutor: ComponentRemoteAnsibleExecutor, executionServiceInput: ExecutionServiceInput): BluePrintRuntimeService<MutableMap<String, JsonNode>> {
- val bluePrintRuntimeService = BluePrintMetadataUtils.getBluePrintRuntime("123456-1000",
- "./../../../../components/model-catalog/blueprint-model/test-blueprint/remote_ansible")
+ private fun createBlueprintRuntimeService(
+ awxRemoteExecutor: ComponentRemoteAnsibleExecutor,
+ executionServiceInput: ExecutionServiceInput
+ ): BluePrintRuntimeService<MutableMap<String, JsonNode>> {
+ val bluePrintRuntimeService = BluePrintMetadataUtils.getBluePrintRuntime(
+ "123456-1000",
+ "./../../../../components/model-catalog/blueprint-model/test-blueprint/remote_ansible"
+ )
awxRemoteExecutor.bluePrintRuntimeService = bluePrintRuntimeService
val workflowName = executionServiceInput.actionIdentifiers.actionName