2 * Copyright © 2019 IBM.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package org.onap.ccsdk.cds.blueprintsprocessor.functions.ansible.executor
19 import com.fasterxml.jackson.databind.JsonNode
20 import com.fasterxml.jackson.databind.ObjectMapper
23 import kotlinx.coroutines.runBlocking
24 import org.junit.Assert.assertEquals
25 import org.junit.Assert.assertTrue
27 import org.junit.runner.RunWith
28 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput
29 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.StepData
30 import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.BluePrintRestLibPropertyService
31 import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.BlueprintWebClientService
32 import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.BlueprintWebClientService.WebClientResponse
33 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
34 import org.onap.ccsdk.cds.controllerblueprints.core.putJsonElement
35 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintRuntimeService
36 import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintMetadataUtils
37 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
38 import org.springframework.test.context.TestPropertySource
39 import org.springframework.test.context.junit4.SpringRunner
41 @RunWith(SpringRunner::class)
42 @TestPropertySource(locations = ["classpath:application-test.properties"])
43 @Suppress("SameParameterValue")
44 class ComponentRemoteAnsibleExecutorTest {
46 private val webClientService = mockk<BlueprintWebClientService>()
49 private const val jtId = 9
50 private const val jobId = 223
52 private val mapper = ObjectMapper()
54 // IMPORTANT: must match the corresponding properties blueprintsprocessor.restclient.awx.* on
55 // "application-test.properties"
56 private const val endpointSelector = """{
58 "url": "http://142.44.184.236",
59 "token": "Bearer J9gEtMDqf7P4YsJ7444fioY9VAhLDIs1"
64 fun testComponentRemoteAnsibleExecutor() {
67 webClientService.exchangeResource("GET", "/api/v2/job_templates/hello_world_job_template/", "")
68 } returns WebClientResponse(200, getJobTemplates(jtId))
70 webClientService.exchangeResource("GET", "/api/v2/job_templates/$jtId/launch/", "")
71 } returns WebClientResponse(200, getJobTemplateLaunch(jtId))
73 webClientService.exchangeResource("GET", "/api/v2/inventories/?name=Demo+Inventory", "")
74 } returns WebClientResponse(200, getInventory())
76 webClientService.exchangeResource(
77 "POST", "/api/v2/job_templates/$jtId/launch/",
78 """{"inventory":1,"extra_vars":{"site_id":"3 - Belmont","tor_group":"vEPC"}}"""
80 } returns WebClientResponse(201, newJobTemplateLaunch(jtId, jobId))
82 webClientService.exchangeResource("GET", "/api/v2/jobs/$jobId/", "")
84 WebClientResponse(200, getJobStatus1(jtId, jobId)),
85 WebClientResponse(200, getJobStatus2(jtId, jobId)),
86 WebClientResponse(200, getJobStatus3(jtId, jobId)),
87 WebClientResponse(200, getJobStatus4(jtId, jobId))
90 webClientService.exchangeResource(
91 "GET", "/api/v2/jobs/$jobId/stdout/?format=txt", "",
92 mapOf("Accept" to "text/plain")
94 } returns WebClientResponse(200, getReport())
95 val selector = mapper.readTree(endpointSelector)
96 val bluePrintRestLibPropertyService = mockk<BluePrintRestLibPropertyService>()
97 every { bluePrintRestLibPropertyService.blueprintWebClientService(selector) } returns webClientService
98 val awxRemoteExecutor = ComponentRemoteAnsibleExecutor(bluePrintRestLibPropertyService, mapper)
99 awxRemoteExecutor.checkDelay = 1
101 val executionServiceInput = JacksonUtils.readValueFromClassPathFile(
102 "payload/requests/sample-remote-ansible-request.json",
103 ExecutionServiceInput::class.java
106 val bluePrintRuntimeService = createBlueprintRuntimeService(awxRemoteExecutor, executionServiceInput)
110 awxRemoteExecutor.applyNB(executionServiceInput)
114 assertTrue(bluePrintRuntimeService.getBluePrintError().errors.isEmpty())
118 fun `handle unknown inventory`() {
121 webClientService.exchangeResource("GET", "/api/v2/job_templates/hello_world_job_template/", "")
122 } returns WebClientResponse(200, getJobTemplates(jtId))
124 webClientService.exchangeResource("GET", "/api/v2/job_templates/$jtId/launch/", "")
125 } returns WebClientResponse(200, getJobTemplateLaunch(jtId))
127 webClientService.exchangeResource("GET", "/api/v2/inventories/?name=Demo+Inventory", "")
128 } returns WebClientResponse(404, "")
129 val selector = mapper.readTree(endpointSelector)
130 val bluePrintRestLibPropertyService = mockk<BluePrintRestLibPropertyService>()
131 every { bluePrintRestLibPropertyService.blueprintWebClientService(selector) } returns webClientService
132 val awxRemoteExecutor = ComponentRemoteAnsibleExecutor(bluePrintRestLibPropertyService, mapper)
133 awxRemoteExecutor.checkDelay = 1
135 val executionServiceInput = JacksonUtils.readValueFromClassPathFile(
136 "payload/requests/remote-ansible-request-full.json",
137 ExecutionServiceInput::class.java
140 val bluePrintRuntimeService = createBlueprintRuntimeService(awxRemoteExecutor, executionServiceInput)
144 awxRemoteExecutor.applyNB(executionServiceInput)
148 val errors = bluePrintRuntimeService.getBluePrintError().errors
149 assertEquals(1, errors.size)
153 fun `handle failure on job submission`() {
156 webClientService.exchangeResource("GET", "/api/v2/job_templates/hello_world_job_template/", "")
157 } returns WebClientResponse(200, getJobTemplates(jtId))
159 webClientService.exchangeResource("GET", "/api/v2/job_templates/$jtId/launch/", "")
160 } returns WebClientResponse(200, getJobTemplateLaunch(jtId))
162 webClientService.exchangeResource("GET", "/api/v2/inventories/?name=Demo+Inventory", "")
163 } returns WebClientResponse(200, getInventory())
165 webClientService.exchangeResource(
166 "POST", "/api/v2/job_templates/$jtId/launch/",
167 """{"limit":"123","tags":"some-tag","skip_tags":"some-skip-tag","inventory":1,"extra_vars":{"site_id":"3 - Belmont","tor_group":"vEPC"}}"""
169 } returns WebClientResponse(500, "")
170 val selector = mapper.readTree(endpointSelector)
171 val bluePrintRestLibPropertyService = mockk<BluePrintRestLibPropertyService>()
172 every { bluePrintRestLibPropertyService.blueprintWebClientService(selector) } returns webClientService
173 val awxRemoteExecutor = ComponentRemoteAnsibleExecutor(bluePrintRestLibPropertyService, mapper)
174 awxRemoteExecutor.checkDelay = 1
176 val executionServiceInput = JacksonUtils.readValueFromClassPathFile(
177 "payload/requests/remote-ansible-request-full.json",
178 ExecutionServiceInput::class.java
181 val bluePrintRuntimeService = createBlueprintRuntimeService(awxRemoteExecutor, executionServiceInput)
185 awxRemoteExecutor.applyNB(executionServiceInput)
189 val errors = bluePrintRuntimeService.getBluePrintError().errors
190 assertEquals(1, errors.size)
193 private fun createBlueprintRuntimeService(
194 awxRemoteExecutor: ComponentRemoteAnsibleExecutor,
195 executionServiceInput: ExecutionServiceInput
196 ): BluePrintRuntimeService<MutableMap<String, JsonNode>> {
197 val bluePrintRuntimeService = BluePrintMetadataUtils.getBluePrintRuntime(
199 "./../../../../components/model-catalog/blueprint-model/test-blueprint/remote_ansible"
201 awxRemoteExecutor.bluePrintRuntimeService = bluePrintRuntimeService
203 val workflowName = executionServiceInput.actionIdentifiers.actionName
205 // Assign Workflow inputs
206 val input = executionServiceInput.payload.get("$workflowName-request")
207 bluePrintRuntimeService.assignWorkflowInputs(workflowName, input)
209 val stepMetaData: MutableMap<String, JsonNode> = hashMapOf()
210 stepMetaData.putJsonElement(BluePrintConstants.PROPERTY_CURRENT_NODE_TEMPLATE, "execute-remote-ansible")
211 stepMetaData.putJsonElement(BluePrintConstants.PROPERTY_CURRENT_INTERFACE, "ComponentRemoteAnsibleExecutor")
212 stepMetaData.putJsonElement(BluePrintConstants.PROPERTY_CURRENT_OPERATION, "process")
214 val stepInputData = StepData().apply {
215 name = "execute-remote-ansible"
216 properties = stepMetaData
218 executionServiceInput.stepData = stepInputData
219 return bluePrintRuntimeService
222 private fun getJobTemplates(jtId: Int) = """{
224 "type": "job_template",
225 "url": "/api/v2/job_templates/$jtId/",
227 "named_url": "/api/v2/job_templates/hello_world_job_template/",
228 "created_by": "/api/v2/users/1/",
229 "modified_by": "/api/v2/users/1/",
230 "labels": "/api/v2/job_templates/$jtId/labels/",
231 "inventory": "/api/v2/inventories/1/",
232 "project": "/api/v2/projects/8/",
233 "extra_credentials": "/api/v2/job_templates/$jtId/extra_credentials/",
234 "credentials": "/api/v2/job_templates/$jtId/credentials/",
235 "last_job": "/api/v2/jobs/222/",
236 "jobs": "/api/v2/job_templates/$jtId/jobs/",
237 "schedules": "/api/v2/job_templates/$jtId/schedules/",
238 "activity_stream": "/api/v2/job_templates/$jtId/activity_stream/",
239 "launch": "/api/v2/job_templates/$jtId/launch/",
240 "notification_templates_any": "/api/v2/job_templates/$jtId/notification_templates_any/",
241 "notification_templates_success": "/api/v2/job_templates/$jtId/notification_templates_success/",
242 "notification_templates_error": "/api/v2/job_templates/$jtId/notification_templates_error/",
243 "access_list": "/api/v2/job_templates/$jtId/access_list/",
244 "survey_spec": "/api/v2/job_templates/$jtId/survey_spec/",
245 "object_roles": "/api/v2/job_templates/$jtId/object_roles/",
246 "instance_groups": "/api/v2/job_templates/$jtId/instance_groups/",
247 "slice_workflow_jobs": "/api/v2/job_templates/$jtId/slice_workflow_jobs/",
248 "copy": "/api/v2/job_templates/$jtId/copy/"
253 "name": "Demo Inventory",
255 "has_active_failures": false,
257 "hosts_with_active_failures": 0,
259 "groups_with_active_failures": 0,
260 "has_inventory_sources": false,
261 "total_inventory_sources": 0,
262 "inventory_sources_with_failures": 0,
263 "organization_id": 1,
268 "name": "cds_playbooks",
269 "description": "CDS - cds_playbooks Project",
275 "name": "hello_world_job_template",
276 "description": "hello_world Runner Job Template",
277 "finished": "2019-06-12T11:20:27.892787Z",
278 "status": "successful",
283 "name": "hello_world_job_template",
284 "description": "hello_world Runner Job Template",
285 "status": "successful",
302 "description": "Can manage all aspects of the job template",
307 "description": "May run the job template",
312 "description": "May view settings for the job template",
317 "user_capabilities": {
335 "status": "successful",
336 "finished": "2019-06-12T11:20:27.892787Z",
341 "status": "successful",
342 "finished": "2019-06-03T18:27:19.114796Z",
347 "status": "successful",
348 "finished": "2019-06-03T18:26:53.606618Z",
353 "status": "successful",
354 "finished": "2019-06-03T18:24:36.072943Z",
359 "status": "successful",
360 "finished": "2019-06-03T18:17:50.616528Z",
365 "status": "successful",
366 "finished": "2019-06-03T18:04:42.995611Z",
371 "status": "successful",
372 "finished": "2019-06-03T17:47:13.983951Z",
377 "status": "successful",
378 "finished": "2019-05-30T15:47:55.700161Z",
383 "status": "successful",
384 "finished": "2019-05-29T14:46:51.615926Z",
389 "status": "successful",
390 "finished": "2019-05-27T20:23:58.656709Z",
394 "extra_credentials": [],
397 "created": "2019-05-21T19:28:05.953730Z",
398 "modified": "2019-05-21T20:06:55.728697Z",
399 "name": "hello_world_job_template",
400 "description": "hello_world Runner Job Template",
404 "playbook": "hello_world.yml",
410 "force_handlers": false,
414 "use_fact_cache": false,
415 "last_job_run": "2019-06-12T11:20:27.892787Z",
416 "last_job_failed": false,
417 "next_job_run": null,
418 "status": "successful",
419 "host_config_key": "",
420 "ask_diff_mode_on_launch": false,
421 "ask_variables_on_launch": true,
422 "ask_limit_on_launch": true,
423 "ask_tags_on_launch": true,
424 "ask_skip_tags_on_launch": true,
425 "ask_job_type_on_launch": false,
426 "ask_verbosity_on_launch": false,
427 "ask_inventory_on_launch": true,
428 "ask_credential_on_launch": true,
429 "survey_enabled": true,
430 "become_enabled": false,
432 "allow_simultaneous": false,
433 "custom_virtualenv": null,
434 "job_slice_count": 1,
436 "vault_credential": null
439 private fun getJobTemplateLaunch(jtId: Int) = """{
440 "can_start_without_user_input": false,
441 "passwords_needed_to_start": [],
442 "ask_variables_on_launch": true,
443 "ask_tags_on_launch": true,
444 "ask_diff_mode_on_launch": false,
445 "ask_skip_tags_on_launch": true,
446 "ask_job_type_on_launch": false,
447 "ask_limit_on_launch": true,
448 "ask_verbosity_on_launch": false,
449 "ask_inventory_on_launch": true,
450 "ask_credential_on_launch": true,
451 "survey_enabled": true,
452 "variables_needed_to_start": [
456 "credential_needed_to_start": false,
457 "inventory_needed_to_start": false,
458 "job_template_data": {
459 "name": "hello_world_job_template",
461 "description": "hello_world Runner Job Template"
472 "name": "Demo Inventory",
478 private fun getInventory() = """{
486 "url": "/api/v2/inventories/1/",
488 "created_by": "/api/v2/users/1/",
489 "modified_by": "/api/v2/users/1/",
490 "hosts": "/api/v2/inventories/1/hosts/",
491 "groups": "/api/v2/inventories/1/groups/",
492 "root_groups": "/api/v2/inventories/1/root_groups/",
493 "variable_data": "/api/v2/inventories/1/variable_data/",
494 "script": "/api/v2/inventories/1/script/",
495 "tree": "/api/v2/inventories/1/tree/",
496 "inventory_sources": "/api/v2/inventories/1/inventory_sources/",
497 "update_inventory_sources": "/api/v2/inventories/1/update_inventory_sources/",
498 "activity_stream": "/api/v2/inventories/1/activity_stream/",
499 "job_templates": "/api/v2/inventories/1/job_templates/",
500 "ad_hoc_commands": "/api/v2/inventories/1/ad_hoc_commands/",
501 "access_list": "/api/v2/inventories/1/access_list/",
502 "object_roles": "/api/v2/inventories/1/object_roles/",
503 "instance_groups": "/api/v2/inventories/1/instance_groups/",
504 "copy": "/api/v2/inventories/1/copy/",
505 "organization": "/api/v2/organizations/1/"
527 "description": "Can manage all aspects of the inventory",
532 "description": "May update project or inventory or group using the configured source update system",
537 "description": "May run ad hoc commands on an inventory",
542 "description": "Can use the inventory in a job template",
547 "description": "May view settings for the inventory",
552 "user_capabilities": {
559 "created": "2019-05-21T15:45:31.954359Z",
560 "modified": "2019-05-21T15:45:31.954378Z",
561 "name": "Demo Inventory",
567 "has_active_failures": false,
569 "hosts_with_active_failures": 0,
571 "groups_with_active_failures": 0,
572 "has_inventory_sources": false,
573 "total_inventory_sources": 0,
574 "inventory_sources_with_failures": 0,
575 "insights_credential": null,
576 "pending_deletion": false
581 private fun newJobTemplateLaunch(jtId: Int, jobId: Int) = """{
583 "ignored_fields": {},
586 "url": "/api/v2/jobs/$jobId/",
588 "created_by": "/api/v2/users/1/",
589 "modified_by": "/api/v2/users/1/",
590 "labels": "/api/v2/jobs/$jobId/labels/",
591 "inventory": "/api/v2/inventories/1/",
592 "project": "/api/v2/projects/8/",
593 "extra_credentials": "/api/v2/jobs/$jobId/extra_credentials/",
594 "credentials": "/api/v2/jobs/$jobId/credentials/",
595 "unified_job_template": "/api/v2/job_templates/$jtId/",
596 "stdout": "/api/v2/jobs/$jobId/stdout/",
597 "job_events": "/api/v2/jobs/$jobId/job_events/",
598 "job_host_summaries": "/api/v2/jobs/$jobId/job_host_summaries/",
599 "activity_stream": "/api/v2/jobs/$jobId/activity_stream/",
600 "notifications": "/api/v2/jobs/$jobId/notifications/",
601 "job_template": "/api/v2/job_templates/$jtId/",
602 "cancel": "/api/v2/jobs/$jobId/cancel/",
603 "create_schedule": "/api/v2/jobs/$jobId/create_schedule/",
604 "relaunch": "/api/v2/jobs/$jobId/relaunch/"
609 "name": "Demo Inventory",
611 "has_active_failures": false,
613 "hosts_with_active_failures": 0,
615 "groups_with_active_failures": 0,
616 "has_inventory_sources": false,
617 "total_inventory_sources": 0,
618 "inventory_sources_with_failures": 0,
619 "organization_id": 1,
624 "name": "cds_playbooks",
625 "description": "CDS - cds_playbooks Project",
631 "name": "hello_world_job_template",
632 "description": "hello_world Runner Job Template"
634 "unified_job_template": {
636 "name": "hello_world_job_template",
637 "description": "hello_world Runner Job Template",
638 "unified_job_type": "job"
652 "user_capabilities": {
660 "extra_credentials": [],
663 "created": "2019-06-12T11:21:26.891986Z",
664 "modified": "2019-06-12T11:21:27.016410Z",
665 "name": "hello_world_job_template",
666 "description": "hello_world Runner Job Template",
670 "playbook": "hello_world.yml",
674 "extra_vars": "{\"tor_group\": \"vEPC\", \"site_id\": \"3 - Belmont\"}",
676 "force_handlers": false,
680 "use_fact_cache": false,
681 "unified_job_template": $jtId,
682 "launch_type": "manual",
691 "job_explanation": "",
692 "execution_node": "",
693 "controller_node": "",
694 "result_traceback": "",
695 "event_processing_finished": false,
696 "job_template": $jtId,
697 "passwords_needed_to_start": [],
698 "ask_diff_mode_on_launch": false,
699 "ask_variables_on_launch": true,
700 "ask_limit_on_launch": true,
701 "ask_tags_on_launch": true,
702 "ask_skip_tags_on_launch": true,
703 "ask_job_type_on_launch": false,
704 "ask_verbosity_on_launch": false,
705 "ask_inventory_on_launch": true,
706 "ask_credential_on_launch": true,
707 "allow_simultaneous": false,
710 "instance_group": null,
712 "job_slice_number": 0,
713 "job_slice_count": 1,
715 "vault_credential": null
718 private fun getJobStatus1(jtId: Int, jobId: Int) = """{
721 "url": "/api/v2/jobs/$jobId/",
723 "created_by": "/api/v2/users/1/",
724 "labels": "/api/v2/jobs/$jobId/labels/",
725 "inventory": "/api/v2/inventories/1/",
726 "project": "/api/v2/projects/8/",
727 "extra_credentials": "/api/v2/jobs/$jobId/extra_credentials/",
728 "credentials": "/api/v2/jobs/$jobId/credentials/",
729 "unified_job_template": "/api/v2/job_templates/$jtId/",
730 "stdout": "/api/v2/jobs/$jobId/stdout/",
731 "job_events": "/api/v2/jobs/$jobId/job_events/",
732 "job_host_summaries": "/api/v2/jobs/$jobId/job_host_summaries/",
733 "activity_stream": "/api/v2/jobs/$jobId/activity_stream/",
734 "notifications": "/api/v2/jobs/$jobId/notifications/",
735 "job_template": "/api/v2/job_templates/$jtId/",
736 "cancel": "/api/v2/jobs/$jobId/cancel/",
737 "create_schedule": "/api/v2/jobs/$jobId/create_schedule/",
738 "relaunch": "/api/v2/jobs/$jobId/relaunch/"
743 "name": "Demo Inventory",
745 "has_active_failures": false,
747 "hosts_with_active_failures": 0,
749 "groups_with_active_failures": 0,
750 "has_inventory_sources": false,
751 "total_inventory_sources": 0,
752 "inventory_sources_with_failures": 0,
753 "organization_id": 1,
758 "name": "cds_playbooks",
759 "description": "CDS - cds_playbooks Project",
765 "name": "hello_world_job_template",
766 "description": "hello_world Runner Job Template"
768 "unified_job_template": {
770 "name": "hello_world_job_template",
771 "description": "hello_world Runner Job Template",
772 "unified_job_type": "job"
784 "user_capabilities": {
792 "extra_credentials": [],
795 "created": "2019-06-12T11:21:26.891986Z",
796 "modified": "2019-06-12T11:21:27.355185Z",
797 "name": "hello_world_job_template",
798 "description": "hello_world Runner Job Template",
802 "playbook": "hello_world.yml",
806 "extra_vars": "{\"tor_group\": \"vEPC\", \"site_id\": \"3 - Belmont\"}",
808 "force_handlers": false,
812 "use_fact_cache": false,
813 "unified_job_template": $jtId,
814 "launch_type": "manual",
823 "job_explanation": "",
824 "execution_node": "awx",
825 "controller_node": "",
826 "result_traceback": "",
827 "event_processing_finished": false,
828 "job_template": $jtId,
829 "passwords_needed_to_start": [],
830 "ask_diff_mode_on_launch": false,
831 "ask_variables_on_launch": true,
832 "ask_limit_on_launch": true,
833 "ask_tags_on_launch": true,
834 "ask_skip_tags_on_launch": true,
835 "ask_job_type_on_launch": false,
836 "ask_verbosity_on_launch": false,
837 "ask_inventory_on_launch": true,
838 "ask_credential_on_launch": true,
839 "allow_simultaneous": false,
844 "job_slice_number": 0,
845 "job_slice_count": 1,
846 "host_status_counts": {},
851 "custom_virtualenv": null,
853 "vault_credential": null
856 private fun getJobStatus2(jtId: Int, jobId: Int) = """{
859 "url": "/api/v2/jobs/$jobId/",
861 "created_by": "/api/v2/users/1/",
862 "labels": "/api/v2/jobs/$jobId/labels/",
863 "inventory": "/api/v2/inventories/1/",
864 "project": "/api/v2/projects/8/",
865 "extra_credentials": "/api/v2/jobs/$jobId/extra_credentials/",
866 "credentials": "/api/v2/jobs/$jobId/credentials/",
867 "unified_job_template": "/api/v2/job_templates/$jtId/",
868 "stdout": "/api/v2/jobs/$jobId/stdout/",
869 "job_events": "/api/v2/jobs/$jobId/job_events/",
870 "job_host_summaries": "/api/v2/jobs/$jobId/job_host_summaries/",
871 "activity_stream": "/api/v2/jobs/$jobId/activity_stream/",
872 "notifications": "/api/v2/jobs/$jobId/notifications/",
873 "job_template": "/api/v2/job_templates/$jtId/",
874 "cancel": "/api/v2/jobs/$jobId/cancel/",
875 "create_schedule": "/api/v2/jobs/$jobId/create_schedule/",
876 "relaunch": "/api/v2/jobs/$jobId/relaunch/"
881 "name": "Demo Inventory",
883 "has_active_failures": false,
885 "hosts_with_active_failures": 0,
887 "groups_with_active_failures": 0,
888 "has_inventory_sources": false,
889 "total_inventory_sources": 0,
890 "inventory_sources_with_failures": 0,
891 "organization_id": 1,
896 "name": "cds_playbooks",
897 "description": "CDS - cds_playbooks Project",
903 "name": "hello_world_job_template",
904 "description": "hello_world Runner Job Template"
906 "unified_job_template": {
908 "name": "hello_world_job_template",
909 "description": "hello_world Runner Job Template",
910 "unified_job_type": "job"
922 "user_capabilities": {
930 "extra_credentials": [],
933 "created": "2019-06-12T11:21:26.891986Z",
934 "modified": "2019-06-12T11:21:27.355185Z",
935 "name": "hello_world_job_template",
936 "description": "hello_world Runner Job Template",
940 "playbook": "hello_world.yml",
944 "extra_vars": "{\"tor_group\": \"vEPC\", \"site_id\": \"3 - Belmont\"}",
946 "force_handlers": false,
950 "use_fact_cache": false,
951 "unified_job_template": $jtId,
952 "launch_type": "manual",
955 "started": "2019-06-12T11:21:27.510766Z",
957 "elapsed": 10.862184,
958 "job_args": "[\"ansible-playbook\", \"-u\", \"root\", \"-i\", \"/tmp/awx_223_ft8hu4p4/tmptmtwllu4\", \"-e\", \"@/tmp/awx_223_ft8hu4p4/env/extravars\", \"hello_world.yml\"]",
959 "job_cwd": "/var/lib/awx/projects/cds_playbooks_folder",
962 "LC_ALL": "en_US.UTF-8",
963 "VIRTUAL_ENV": "/var/lib/awx/venv/ansible",
964 "PATH": "/var/lib/awx/venv/ansible/bin:/var/lib/awx/venv/awx/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
965 "SUPERVISOR_GROUP_NAME": "tower-processes",
966 "PWD": "/var/lib/awx",
967 "LANG": "en_US.UTF-8",
969 "SUPERVISOR_ENABLED": "1",
970 "HOME": "/var/lib/awx",
972 "LANGUAGE": "en_US.UTF-8",
973 "LC_CTYPE": "en_US.UTF-8",
974 "SUPERVISOR_PROCESS_NAME": "dispatcher",
975 "SUPERVISOR_SERVER_URL": "unix:///tmp/supervisor.sock",
976 "DJANGO_SETTINGS_MODULE": "awx.settings.production",
977 "DJANGO_LIVE_TEST_SERVER_ADDRESS": "localhost:9013-9199",
979 "ANSIBLE_FORCE_COLOR": "True",
980 "ANSIBLE_HOST_KEY_CHECKING": "False",
981 "ANSIBLE_INVENTORY_UNPARSED_FAILED": "True",
982 "ANSIBLE_PARAMIKO_RECORD_HOST_KEYS": "False",
983 "ANSIBLE_VENV_PATH": "/var/lib/awx/venv/ansible",
984 "AWX_PRIVATE_DATA_DIR": "/tmp/awx_223_ft8hu4p4",
985 "PYTHONPATH": "/var/lib/awx/venv/ansible/lib/python2.7/site-packages:/var/lib/awx/venv/awx/lib64/python3.6/site-packages/awx/lib:",
988 "PROJECT_REVISION": "",
989 "ANSIBLE_RETRY_FILES_ENABLED": "False",
990 "MAX_EVENT_RES": "700000",
991 "ANSIBLE_CALLBACK_PLUGINS": "/var/lib/awx/venv/awx/lib64/python3.6/site-packages/awx/plugins/callback",
992 "AWX_HOST": "https://towerhost",
993 "ANSIBLE_SSH_CONTROL_PATH_DIR": "/tmp/awx_223_ft8hu4p4/cp",
994 "ANSIBLE_STDOUT_CALLBACK": "awx_display",
995 "AWX_ISOLATED_DATA_DIR": "/tmp/awx_223_ft8hu4p4/artifacts/$jobId"
997 "job_explanation": "",
998 "execution_node": "awx",
999 "controller_node": "",
1000 "result_traceback": "",
1001 "event_processing_finished": false,
1002 "job_template": $jtId,
1003 "passwords_needed_to_start": [],
1004 "ask_diff_mode_on_launch": false,
1005 "ask_variables_on_launch": true,
1006 "ask_limit_on_launch": true,
1007 "ask_tags_on_launch": true,
1008 "ask_skip_tags_on_launch": true,
1009 "ask_job_type_on_launch": false,
1010 "ask_verbosity_on_launch": false,
1011 "ask_inventory_on_launch": true,
1012 "ask_credential_on_launch": true,
1013 "allow_simultaneous": false,
1016 "instance_group": 1,
1018 "job_slice_number": 0,
1019 "job_slice_count": 1,
1020 "host_status_counts": {},
1021 "playbook_counts": {
1025 "custom_virtualenv": "/var/lib/awx/venv/ansible",
1027 "vault_credential": null
1030 private fun getJobStatus3(jtId: Int, jobId: Int) = """{
1033 "url": "/api/v2/jobs/$jobId/",
1035 "created_by": "/api/v2/users/1/",
1036 "labels": "/api/v2/jobs/$jobId/labels/",
1037 "inventory": "/api/v2/inventories/1/",
1038 "project": "/api/v2/projects/8/",
1039 "extra_credentials": "/api/v2/jobs/$jobId/extra_credentials/",
1040 "credentials": "/api/v2/jobs/$jobId/credentials/",
1041 "unified_job_template": "/api/v2/job_templates/$jtId/",
1042 "stdout": "/api/v2/jobs/$jobId/stdout/",
1043 "job_events": "/api/v2/jobs/$jobId/job_events/",
1044 "job_host_summaries": "/api/v2/jobs/$jobId/job_host_summaries/",
1045 "activity_stream": "/api/v2/jobs/$jobId/activity_stream/",
1046 "notifications": "/api/v2/jobs/$jobId/notifications/",
1047 "job_template": "/api/v2/job_templates/$jtId/",
1048 "cancel": "/api/v2/jobs/$jobId/cancel/",
1049 "create_schedule": "/api/v2/jobs/$jobId/create_schedule/",
1050 "relaunch": "/api/v2/jobs/$jobId/relaunch/"
1055 "name": "Demo Inventory",
1057 "has_active_failures": false,
1059 "hosts_with_active_failures": 0,
1061 "groups_with_active_failures": 0,
1062 "has_inventory_sources": false,
1063 "total_inventory_sources": 0,
1064 "inventory_sources_with_failures": 0,
1065 "organization_id": 1,
1070 "name": "cds_playbooks",
1071 "description": "CDS - cds_playbooks Project",
1077 "name": "hello_world_job_template",
1078 "description": "hello_world Runner Job Template"
1080 "unified_job_template": {
1082 "name": "hello_world_job_template",
1083 "description": "hello_world Runner Job Template",
1084 "unified_job_type": "job"
1092 "username": "admin",
1096 "user_capabilities": {
1104 "extra_credentials": [],
1107 "created": "2019-06-12T11:21:26.891986Z",
1108 "modified": "2019-06-12T11:21:27.355185Z",
1109 "name": "hello_world_job_template",
1110 "description": "hello_world Runner Job Template",
1114 "playbook": "hello_world.yml",
1118 "extra_vars": "{\"tor_group\": \"vEPC\", \"site_id\": \"3 - Belmont\"}",
1120 "force_handlers": false,
1122 "start_at_task": "",
1124 "use_fact_cache": false,
1125 "unified_job_template": $jtId,
1126 "launch_type": "manual",
1127 "status": "running",
1129 "started": "2019-06-12T11:21:27.510766Z",
1131 "elapsed": 21.297881,
1132 "job_args": "[\"ansible-playbook\", \"-u\", \"root\", \"-i\", \"/tmp/awx_223_ft8hu4p4/tmptmtwllu4\", \"-e\", \"@/tmp/awx_223_ft8hu4p4/env/extravars\", \"hello_world.yml\"]",
1133 "job_cwd": "/var/lib/awx/projects/cds_playbooks_folder",
1136 "LC_ALL": "en_US.UTF-8",
1137 "VIRTUAL_ENV": "/var/lib/awx/venv/ansible",
1138 "PATH": "/var/lib/awx/venv/ansible/bin:/var/lib/awx/venv/awx/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
1139 "SUPERVISOR_GROUP_NAME": "tower-processes",
1140 "PWD": "/var/lib/awx",
1141 "LANG": "en_US.UTF-8",
1143 "SUPERVISOR_ENABLED": "1",
1144 "HOME": "/var/lib/awx",
1146 "LANGUAGE": "en_US.UTF-8",
1147 "LC_CTYPE": "en_US.UTF-8",
1148 "SUPERVISOR_PROCESS_NAME": "dispatcher",
1149 "SUPERVISOR_SERVER_URL": "unix:///tmp/supervisor.sock",
1150 "DJANGO_SETTINGS_MODULE": "awx.settings.production",
1151 "DJANGO_LIVE_TEST_SERVER_ADDRESS": "localhost:9013-9199",
1153 "ANSIBLE_FORCE_COLOR": "True",
1154 "ANSIBLE_HOST_KEY_CHECKING": "False",
1155 "ANSIBLE_INVENTORY_UNPARSED_FAILED": "True",
1156 "ANSIBLE_PARAMIKO_RECORD_HOST_KEYS": "False",
1157 "ANSIBLE_VENV_PATH": "/var/lib/awx/venv/ansible",
1158 "AWX_PRIVATE_DATA_DIR": "/tmp/awx_223_ft8hu4p4",
1159 "PYTHONPATH": "/var/lib/awx/venv/ansible/lib/python2.7/site-packages:/var/lib/awx/venv/awx/lib64/python3.6/site-packages/awx/lib:",
1161 "INVENTORY_ID": "1",
1162 "PROJECT_REVISION": "",
1163 "ANSIBLE_RETRY_FILES_ENABLED": "False",
1164 "MAX_EVENT_RES": "700000",
1165 "ANSIBLE_CALLBACK_PLUGINS": "/var/lib/awx/venv/awx/lib64/python3.6/site-packages/awx/plugins/callback",
1166 "AWX_HOST": "https://towerhost",
1167 "ANSIBLE_SSH_CONTROL_PATH_DIR": "/tmp/awx_223_ft8hu4p4/cp",
1168 "ANSIBLE_STDOUT_CALLBACK": "awx_display",
1169 "AWX_ISOLATED_DATA_DIR": "/tmp/awx_223_ft8hu4p4/artifacts/$jobId"
1171 "job_explanation": "",
1172 "execution_node": "awx",
1173 "controller_node": "",
1174 "result_traceback": "",
1175 "event_processing_finished": false,
1176 "job_template": $jtId,
1177 "passwords_needed_to_start": [],
1178 "ask_diff_mode_on_launch": false,
1179 "ask_variables_on_launch": true,
1180 "ask_limit_on_launch": true,
1181 "ask_tags_on_launch": true,
1182 "ask_skip_tags_on_launch": true,
1183 "ask_job_type_on_launch": false,
1184 "ask_verbosity_on_launch": false,
1185 "ask_inventory_on_launch": true,
1186 "ask_credential_on_launch": true,
1187 "allow_simultaneous": false,
1190 "instance_group": 1,
1192 "job_slice_number": 0,
1193 "job_slice_count": 1,
1194 "host_status_counts": {},
1195 "playbook_counts": {
1199 "custom_virtualenv": "/var/lib/awx/venv/ansible",
1201 "vault_credential": null
1204 private fun getJobStatus4(jtId: Int, jobId: Int) = """{
1207 "url": "/api/v2/jobs/$jobId/",
1209 "created_by": "/api/v2/users/1/",
1210 "labels": "/api/v2/jobs/$jobId/labels/",
1211 "inventory": "/api/v2/inventories/1/",
1212 "project": "/api/v2/projects/8/",
1213 "extra_credentials": "/api/v2/jobs/$jobId/extra_credentials/",
1214 "credentials": "/api/v2/jobs/$jobId/credentials/",
1215 "unified_job_template": "/api/v2/job_templates/$jtId/",
1216 "stdout": "/api/v2/jobs/$jobId/stdout/",
1217 "job_events": "/api/v2/jobs/$jobId/job_events/",
1218 "job_host_summaries": "/api/v2/jobs/$jobId/job_host_summaries/",
1219 "activity_stream": "/api/v2/jobs/$jobId/activity_stream/",
1220 "notifications": "/api/v2/jobs/$jobId/notifications/",
1221 "job_template": "/api/v2/job_templates/$jtId/",
1222 "cancel": "/api/v2/jobs/$jobId/cancel/",
1223 "create_schedule": "/api/v2/jobs/$jobId/create_schedule/",
1224 "relaunch": "/api/v2/jobs/$jobId/relaunch/"
1229 "name": "Demo Inventory",
1231 "has_active_failures": false,
1233 "hosts_with_active_failures": 0,
1235 "groups_with_active_failures": 0,
1236 "has_inventory_sources": false,
1237 "total_inventory_sources": 0,
1238 "inventory_sources_with_failures": 0,
1239 "organization_id": 1,
1244 "name": "cds_playbooks",
1245 "description": "CDS - cds_playbooks Project",
1251 "name": "hello_world_job_template",
1252 "description": "hello_world Runner Job Template"
1254 "unified_job_template": {
1256 "name": "hello_world_job_template",
1257 "description": "hello_world Runner Job Template",
1258 "unified_job_type": "job"
1266 "username": "admin",
1270 "user_capabilities": {
1278 "extra_credentials": [],
1281 "created": "2019-06-12T11:21:26.891986Z",
1282 "modified": "2019-06-12T11:21:27.355185Z",
1283 "name": "hello_world_job_template",
1284 "description": "hello_world Runner Job Template",
1288 "playbook": "hello_world.yml",
1292 "extra_vars": "{\"tor_group\": \"vEPC\", \"site_id\": \"3 - Belmont\"}",
1294 "force_handlers": false,
1296 "start_at_task": "",
1298 "use_fact_cache": false,
1299 "unified_job_template": $jtId,
1300 "launch_type": "manual",
1301 "status": "successful",
1303 "started": "2019-06-12T11:21:27.510766Z",
1304 "finished": "2019-06-12T11:21:48.993385Z",
1306 "job_args": "[\"ansible-playbook\", \"-u\", \"root\", \"-i\", \"/tmp/awx_223_ft8hu4p4/tmptmtwllu4\", \"-e\", \"@/tmp/awx_223_ft8hu4p4/env/extravars\", \"hello_world.yml\"]",
1307 "job_cwd": "/var/lib/awx/projects/cds_playbooks_folder",
1310 "LC_ALL": "en_US.UTF-8",
1311 "VIRTUAL_ENV": "/var/lib/awx/venv/ansible",
1312 "PATH": "/var/lib/awx/venv/ansible/bin:/var/lib/awx/venv/awx/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
1313 "SUPERVISOR_GROUP_NAME": "tower-processes",
1314 "PWD": "/var/lib/awx",
1315 "LANG": "en_US.UTF-8",
1317 "SUPERVISOR_ENABLED": "1",
1318 "HOME": "/var/lib/awx",
1320 "LANGUAGE": "en_US.UTF-8",
1321 "LC_CTYPE": "en_US.UTF-8",
1322 "SUPERVISOR_PROCESS_NAME": "dispatcher",
1323 "SUPERVISOR_SERVER_URL": "unix:///tmp/supervisor.sock",
1324 "DJANGO_SETTINGS_MODULE": "awx.settings.production",
1325 "DJANGO_LIVE_TEST_SERVER_ADDRESS": "localhost:9013-9199",
1327 "ANSIBLE_FORCE_COLOR": "True",
1328 "ANSIBLE_HOST_KEY_CHECKING": "False",
1329 "ANSIBLE_INVENTORY_UNPARSED_FAILED": "True",
1330 "ANSIBLE_PARAMIKO_RECORD_HOST_KEYS": "False",
1331 "ANSIBLE_VENV_PATH": "/var/lib/awx/venv/ansible",
1332 "AWX_PRIVATE_DATA_DIR": "/tmp/awx_223_ft8hu4p4",
1333 "PYTHONPATH": "/var/lib/awx/venv/ansible/lib/python2.7/site-packages:/var/lib/awx/venv/awx/lib64/python3.6/site-packages/awx/lib:",
1335 "INVENTORY_ID": "1",
1336 "PROJECT_REVISION": "",
1337 "ANSIBLE_RETRY_FILES_ENABLED": "False",
1338 "MAX_EVENT_RES": "700000",
1339 "ANSIBLE_CALLBACK_PLUGINS": "/var/lib/awx/venv/awx/lib64/python3.6/site-packages/awx/plugins/callback",
1340 "AWX_HOST": "https://towerhost",
1341 "ANSIBLE_SSH_CONTROL_PATH_DIR": "/tmp/awx_223_ft8hu4p4/cp",
1342 "ANSIBLE_STDOUT_CALLBACK": "awx_display",
1343 "AWX_ISOLATED_DATA_DIR": "/tmp/awx_223_ft8hu4p4/artifacts/$jobId"
1345 "job_explanation": "",
1346 "execution_node": "awx",
1347 "controller_node": "",
1348 "result_traceback": "",
1349 "event_processing_finished": true,
1350 "job_template": $jtId,
1351 "passwords_needed_to_start": [],
1352 "ask_diff_mode_on_launch": false,
1353 "ask_variables_on_launch": true,
1354 "ask_limit_on_launch": true,
1355 "ask_tags_on_launch": true,
1356 "ask_skip_tags_on_launch": true,
1357 "ask_job_type_on_launch": false,
1358 "ask_verbosity_on_launch": false,
1359 "ask_inventory_on_launch": true,
1360 "ask_credential_on_launch": true,
1361 "allow_simultaneous": false,
1364 "instance_group": 1,
1366 "job_slice_number": 0,
1367 "job_slice_count": 1,
1368 "host_status_counts": {
1371 "playbook_counts": {
1375 "custom_virtualenv": "/var/lib/awx/venv/ansible",
1377 "vault_credential": null
1380 private fun getReport() = """
1382 PLAY [Hello World Sample] ******************************************************
1384 TASK [Gathering Facts] *********************************************************
1387 TASK [Hello Message] ***********************************************************
1388 ok: [localhost] => {
1389 "msg": "Hello World!"
1392 PLAY RECAP *********************************************************************
1393 localhost : ok=2 changed=0 unreachable=0 failed=0