Revert "Renaming Files having BluePrint to have Blueprint"
[ccsdk/cds.git] / ms / blueprintsprocessor / functions / ansible-awx-executor / src / test / kotlin / org / onap / ccsdk / cds / blueprintsprocessor / functions / ansible / executor / ComponentRemoteAnsibleExecutorTest.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.ansible.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.Assert.assertEquals
25 import org.junit.Assert.assertTrue
26 import org.junit.Test
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
40
41 @RunWith(SpringRunner::class)
42 @TestPropertySource(locations = ["classpath:application-test.properties"])
43 @Suppress("SameParameterValue")
44 class ComponentRemoteAnsibleExecutorTest {
45
46     private val webClientService = mockk<BlueprintWebClientService>()
47
48     companion object {
49
50         private const val jtId = 9
51         private const val jobId = 223
52
53         private val mapper = ObjectMapper()
54
55         // IMPORTANT: must match the corresponding properties blueprintsprocessor.restclient.awx.* on
56         // "application-test.properties"
57         private const val endpointSelector = """{
58             "type": "token-auth",
59             "url": "http://142.44.184.236",
60             "token": "Bearer J9gEtMDqf7P4YsJ7444fioY9VAhLDIs1"
61             }"""
62     }
63
64     @Test
65     fun testComponentRemoteAnsibleExecutor() {
66
67         every {
68             webClientService.exchangeResource("GET", "/api/v2/job_templates/hello_world_job_template/", "")
69         } returns WebClientResponse(200, getJobTemplates(jtId))
70         every {
71             webClientService.exchangeResource("GET", "/api/v2/job_templates/$jtId/launch/", "")
72         } returns WebClientResponse(200, getJobTemplateLaunch(jtId))
73         every {
74             webClientService.exchangeResource("GET", "/api/v2/inventories/?name=Demo+Inventory", "")
75         } returns WebClientResponse(200, getInventory())
76         every {
77             webClientService.exchangeResource(
78                 "POST", "/api/v2/job_templates/$jtId/launch/",
79                 """{"inventory":1,"extra_vars":{"site_id":"3 - Belmont","tor_group":"vEPC"}}"""
80             )
81         } returns WebClientResponse(201, newJobTemplateLaunch(jtId, jobId))
82         every {
83             webClientService.exchangeResource("GET", "/api/v2/jobs/$jobId/", "")
84         } returnsMany listOf(
85             WebClientResponse(200, getJobStatus1(jtId, jobId)),
86             WebClientResponse(200, getJobStatus2(jtId, jobId)),
87             WebClientResponse(200, getJobStatus3(jtId, jobId)),
88             WebClientResponse(200, getJobStatus4(jtId, jobId))
89         )
90         every {
91             webClientService.exchangeResource(
92                 "GET", "/api/v2/jobs/$jobId/stdout/?format=txt", "",
93                 mapOf("Accept" to "text/plain")
94             )
95         } returns WebClientResponse(200, getReport())
96         val selector = mapper.readTree(endpointSelector)
97         val bluePrintRestLibPropertyService = mockk<BluePrintRestLibPropertyService>()
98         every { bluePrintRestLibPropertyService.blueprintWebClientService(selector) } returns webClientService
99         val awxRemoteExecutor = ComponentRemoteAnsibleExecutor(bluePrintRestLibPropertyService, mapper)
100         awxRemoteExecutor.checkDelay = 1
101
102         val executionServiceInput = JacksonUtils.readValueFromClassPathFile(
103             "payload/requests/sample-remote-ansible-request.json",
104             ExecutionServiceInput::class.java
105         )!!
106
107         val bluePrintRuntimeService = createBlueprintRuntimeService(awxRemoteExecutor, executionServiceInput)
108
109         // when
110         runBlocking {
111             awxRemoteExecutor.applyNB(executionServiceInput)
112         }
113
114         // then
115         assertTrue(bluePrintRuntimeService.getBluePrintError().allErrors().isEmpty())
116     }
117
118     @Test
119     fun `handle unknown inventory`() {
120
121         every {
122             webClientService.exchangeResource("GET", "/api/v2/job_templates/hello_world_job_template/", "")
123         } returns WebClientResponse(200, getJobTemplates(jtId))
124         every {
125             webClientService.exchangeResource("GET", "/api/v2/job_templates/$jtId/launch/", "")
126         } returns WebClientResponse(200, getJobTemplateLaunch(jtId))
127         every {
128             webClientService.exchangeResource("GET", "/api/v2/inventories/?name=Demo+Inventory", "")
129         } returns WebClientResponse(404, "")
130         val selector = mapper.readTree(endpointSelector)
131         val bluePrintRestLibPropertyService = mockk<BluePrintRestLibPropertyService>()
132         every { bluePrintRestLibPropertyService.blueprintWebClientService(selector) } returns webClientService
133         val awxRemoteExecutor = ComponentRemoteAnsibleExecutor(bluePrintRestLibPropertyService, mapper)
134         awxRemoteExecutor.checkDelay = 1
135
136         val executionServiceInput = JacksonUtils.readValueFromClassPathFile(
137             "payload/requests/remote-ansible-request-full.json",
138             ExecutionServiceInput::class.java
139         )!!
140
141         val bluePrintRuntimeService = createBlueprintRuntimeService(awxRemoteExecutor, executionServiceInput)
142
143         // when
144         runBlocking {
145             awxRemoteExecutor.applyNB(executionServiceInput)
146         }
147
148         // then
149         val errors = bluePrintRuntimeService.getBluePrintError().allErrors()
150         assertEquals(1, errors.size)
151     }
152
153     @Test
154     fun `handle failure on job submission`() {
155
156         every {
157             webClientService.exchangeResource("GET", "/api/v2/job_templates/hello_world_job_template/", "")
158         } returns WebClientResponse(200, getJobTemplates(jtId))
159         every {
160             webClientService.exchangeResource("GET", "/api/v2/job_templates/$jtId/launch/", "")
161         } returns WebClientResponse(200, getJobTemplateLaunch(jtId))
162         every {
163             webClientService.exchangeResource("GET", "/api/v2/inventories/?name=Demo+Inventory", "")
164         } returns WebClientResponse(200, getInventory())
165         every {
166             webClientService.exchangeResource(
167                 "POST", "/api/v2/job_templates/$jtId/launch/",
168                 """{"limit":"123","tags":"some-tag","skip_tags":"some-skip-tag","inventory":1,"extra_vars":{"site_id":"3 - Belmont","tor_group":"vEPC"}}"""
169             )
170         } returns WebClientResponse(500, "")
171         val selector = mapper.readTree(endpointSelector)
172         val bluePrintRestLibPropertyService = mockk<BluePrintRestLibPropertyService>()
173         every { bluePrintRestLibPropertyService.blueprintWebClientService(selector) } returns webClientService
174         val awxRemoteExecutor = ComponentRemoteAnsibleExecutor(bluePrintRestLibPropertyService, mapper)
175         awxRemoteExecutor.checkDelay = 1
176
177         val executionServiceInput = JacksonUtils.readValueFromClassPathFile(
178             "payload/requests/remote-ansible-request-full.json",
179             ExecutionServiceInput::class.java
180         )!!
181
182         val bluePrintRuntimeService = createBlueprintRuntimeService(awxRemoteExecutor, executionServiceInput)
183
184         // when
185         runBlocking {
186             awxRemoteExecutor.applyNB(executionServiceInput)
187         }
188
189         // then
190         val errors = bluePrintRuntimeService.getBluePrintError().allErrors()
191         assertEquals(1, errors.size)
192     }
193
194     private fun createBlueprintRuntimeService(
195         awxRemoteExecutor: ComponentRemoteAnsibleExecutor,
196         executionServiceInput: ExecutionServiceInput
197     ): BluePrintRuntimeService<MutableMap<String, JsonNode>> {
198         val bluePrintRuntimeService = BluePrintMetadataUtils.bluePrintRuntime(
199             "123456-1000",
200             "./../../../../components/model-catalog/blueprint-model/test-blueprint/remote_ansible"
201         )
202         awxRemoteExecutor.bluePrintRuntimeService = bluePrintRuntimeService
203
204         val workflowName = executionServiceInput.actionIdentifiers.actionName
205
206         // Assign Workflow inputs
207         val input = executionServiceInput.payload.get("$workflowName-request")
208         bluePrintRuntimeService.assignWorkflowInputs(workflowName, input)
209
210         val stepMetaData: MutableMap<String, JsonNode> = hashMapOf()
211         stepMetaData.putJsonElement(BluePrintConstants.PROPERTY_CURRENT_NODE_TEMPLATE, "execute-remote-ansible")
212         stepMetaData.putJsonElement(BluePrintConstants.PROPERTY_CURRENT_INTERFACE, "ComponentRemoteAnsibleExecutor")
213         stepMetaData.putJsonElement(BluePrintConstants.PROPERTY_CURRENT_OPERATION, "process")
214
215         val stepInputData = StepData().apply {
216             name = "execute-remote-ansible"
217             properties = stepMetaData
218         }
219         executionServiceInput.stepData = stepInputData
220         return bluePrintRuntimeService
221     }
222
223     private fun getJobTemplates(jtId: Int) = """{
224       "id": $jtId,
225       "type": "job_template",
226       "url": "/api/v2/job_templates/$jtId/",
227       "related": {
228         "named_url": "/api/v2/job_templates/hello_world_job_template/",
229         "created_by": "/api/v2/users/1/",
230         "modified_by": "/api/v2/users/1/",
231         "labels": "/api/v2/job_templates/$jtId/labels/",
232         "inventory": "/api/v2/inventories/1/",
233         "project": "/api/v2/projects/8/",
234         "extra_credentials": "/api/v2/job_templates/$jtId/extra_credentials/",
235         "credentials": "/api/v2/job_templates/$jtId/credentials/",
236         "last_job": "/api/v2/jobs/222/",
237         "jobs": "/api/v2/job_templates/$jtId/jobs/",
238         "schedules": "/api/v2/job_templates/$jtId/schedules/",
239         "activity_stream": "/api/v2/job_templates/$jtId/activity_stream/",
240         "launch": "/api/v2/job_templates/$jtId/launch/",
241         "notification_templates_any": "/api/v2/job_templates/$jtId/notification_templates_any/",
242         "notification_templates_success": "/api/v2/job_templates/$jtId/notification_templates_success/",
243         "notification_templates_error": "/api/v2/job_templates/$jtId/notification_templates_error/",
244         "access_list": "/api/v2/job_templates/$jtId/access_list/",
245         "survey_spec": "/api/v2/job_templates/$jtId/survey_spec/",
246         "object_roles": "/api/v2/job_templates/$jtId/object_roles/",
247         "instance_groups": "/api/v2/job_templates/$jtId/instance_groups/",
248         "slice_workflow_jobs": "/api/v2/job_templates/$jtId/slice_workflow_jobs/",
249         "copy": "/api/v2/job_templates/$jtId/copy/"
250       },
251       "summary_fields": {
252         "inventory": {
253           "id": 1,
254           "name": "Demo Inventory",
255           "description": "",
256           "has_active_failures": false,
257           "total_hosts": 1,
258           "hosts_with_active_failures": 0,
259           "total_groups": 0,
260           "groups_with_active_failures": 0,
261           "has_inventory_sources": false,
262           "total_inventory_sources": 0,
263           "inventory_sources_with_failures": 0,
264           "organization_id": 1,
265           "kind": ""
266         },
267         "project": {
268           "id": 8,
269           "name": "cds_playbooks",
270           "description": "CDS - cds_playbooks Project",
271           "status": "ok",
272           "scm_type": ""
273         },
274         "last_job": {
275           "id": 222,
276           "name": "hello_world_job_template",
277           "description": "hello_world Runner Job Template",
278           "finished": "2019-06-12T11:20:27.892787Z",
279           "status": "successful",
280           "failed": false
281         },
282         "last_update": {
283           "id": 222,
284           "name": "hello_world_job_template",
285           "description": "hello_world Runner Job Template",
286           "status": "successful",
287           "failed": false
288         },
289         "created_by": {
290           "id": 1,
291           "username": "admin",
292           "first_name": "",
293           "last_name": ""
294         },
295         "modified_by": {
296           "id": 1,
297           "username": "admin",
298           "first_name": "",
299           "last_name": ""
300         },
301         "object_roles": {
302           "admin_role": {
303             "description": "Can manage all aspects of the job template",
304             "name": "Admin",
305             "id": 51
306           },
307           "execute_role": {
308             "description": "May run the job template",
309             "name": "Execute",
310             "id": 52
311           },
312           "read_role": {
313             "description": "May view settings for the job template",
314             "name": "Read",
315             "id": 53
316           }
317         },
318         "user_capabilities": {
319           "edit": true,
320           "delete": true,
321           "start": true,
322           "schedule": true,
323           "copy": true
324         },
325         "labels": {
326           "count": 0,
327           "results": []
328         },
329         "survey": {
330           "title": "",
331           "description": ""
332         },
333         "recent_jobs": [
334           {
335             "id": 222,
336             "status": "successful",
337             "finished": "2019-06-12T11:20:27.892787Z",
338             "type": "job"
339           },
340           {
341             "id": 65,
342             "status": "successful",
343             "finished": "2019-06-03T18:27:19.114796Z",
344             "type": "job"
345           },
346           {
347             "id": 64,
348             "status": "successful",
349             "finished": "2019-06-03T18:26:53.606618Z",
350             "type": "job"
351           },
352           {
353             "id": 63,
354             "status": "successful",
355             "finished": "2019-06-03T18:24:36.072943Z",
356             "type": "job"
357           },
358           {
359             "id": 62,
360             "status": "successful",
361             "finished": "2019-06-03T18:17:50.616528Z",
362             "type": "job"
363           },
364           {
365             "id": 61,
366             "status": "successful",
367             "finished": "2019-06-03T18:04:42.995611Z",
368             "type": "job"
369           },
370           {
371             "id": 60,
372             "status": "successful",
373             "finished": "2019-06-03T17:47:13.983951Z",
374             "type": "job"
375           },
376           {
377             "id": 50,
378             "status": "successful",
379             "finished": "2019-05-30T15:47:55.700161Z",
380             "type": "job"
381           },
382           {
383             "id": 49,
384             "status": "successful",
385             "finished": "2019-05-29T14:46:51.615926Z",
386             "type": "job"
387           },
388           {
389             "id": 47,
390             "status": "successful",
391             "finished": "2019-05-27T20:23:58.656709Z",
392             "type": "job"
393           }
394         ],
395         "extra_credentials": [],
396         "credentials": []
397       },
398       "created": "2019-05-21T19:28:05.953730Z",
399       "modified": "2019-05-21T20:06:55.728697Z",
400       "name": "hello_world_job_template",
401       "description": "hello_world Runner Job Template",
402       "job_type": "run",
403       "inventory": 1,
404       "project": 8,
405       "playbook": "hello_world.yml",
406       "forks": 0,
407       "limit": "",
408       "verbosity": 0,
409       "extra_vars": "",
410       "job_tags": "",
411       "force_handlers": false,
412       "skip_tags": "",
413       "start_at_task": "",
414       "timeout": 0,
415       "use_fact_cache": false,
416       "last_job_run": "2019-06-12T11:20:27.892787Z",
417       "last_job_failed": false,
418       "next_job_run": null,
419       "status": "successful",
420       "host_config_key": "",
421       "ask_diff_mode_on_launch": false,
422       "ask_variables_on_launch": true,
423       "ask_limit_on_launch": true,
424       "ask_tags_on_launch": true,
425       "ask_skip_tags_on_launch": true,
426       "ask_job_type_on_launch": false,
427       "ask_verbosity_on_launch": false,
428       "ask_inventory_on_launch": true,
429       "ask_credential_on_launch": true,
430       "survey_enabled": true,
431       "become_enabled": false,
432       "diff_mode": false,
433       "allow_simultaneous": false,
434       "custom_virtualenv": null,
435       "job_slice_count": 1,
436       "credential": null,
437       "vault_credential": null
438     }"""
439
440     private fun getJobTemplateLaunch(jtId: Int) = """{
441       "can_start_without_user_input": false,
442       "passwords_needed_to_start": [],
443       "ask_variables_on_launch": true,
444       "ask_tags_on_launch": true,
445       "ask_diff_mode_on_launch": false,
446       "ask_skip_tags_on_launch": true,
447       "ask_job_type_on_launch": false,
448       "ask_limit_on_launch": true,
449       "ask_verbosity_on_launch": false,
450       "ask_inventory_on_launch": true,
451       "ask_credential_on_launch": true,
452       "survey_enabled": true,
453       "variables_needed_to_start": [
454         "tor_group",
455         "site_id"
456       ],
457       "credential_needed_to_start": false,
458       "inventory_needed_to_start": false,
459       "job_template_data": {
460         "name": "hello_world_job_template",
461         "id": $jtId,
462         "description": "hello_world Runner Job Template"
463       },
464       "defaults": {
465         "extra_vars": "",
466         "diff_mode": false,
467         "limit": "",
468         "job_tags": "",
469         "skip_tags": "",
470         "job_type": "run",
471         "verbosity": 0,
472         "inventory": {
473           "name": "Demo Inventory",
474           "id": 1
475         }
476       }
477     }"""
478
479     private fun getInventory() = """{
480           "count": 1,
481           "next": null,
482           "previous": null,
483           "results": [
484             {
485               "id": 1,
486               "type": "inventory",
487               "url": "/api/v2/inventories/1/",
488               "related": {
489                 "created_by": "/api/v2/users/1/",
490                 "modified_by": "/api/v2/users/1/",
491                 "hosts": "/api/v2/inventories/1/hosts/",
492                 "groups": "/api/v2/inventories/1/groups/",
493                 "root_groups": "/api/v2/inventories/1/root_groups/",
494                 "variable_data": "/api/v2/inventories/1/variable_data/",
495                 "script": "/api/v2/inventories/1/script/",
496                 "tree": "/api/v2/inventories/1/tree/",
497                 "inventory_sources": "/api/v2/inventories/1/inventory_sources/",
498                 "update_inventory_sources": "/api/v2/inventories/1/update_inventory_sources/",
499                 "activity_stream": "/api/v2/inventories/1/activity_stream/",
500                 "job_templates": "/api/v2/inventories/1/job_templates/",
501                 "ad_hoc_commands": "/api/v2/inventories/1/ad_hoc_commands/",
502                 "access_list": "/api/v2/inventories/1/access_list/",
503                 "object_roles": "/api/v2/inventories/1/object_roles/",
504                 "instance_groups": "/api/v2/inventories/1/instance_groups/",
505                 "copy": "/api/v2/inventories/1/copy/",
506                 "organization": "/api/v2/organizations/1/"
507               },
508               "summary_fields": {
509                 "organization": {
510                   "id": 1,
511                   "name": "Default",
512                   "description": ""
513                 },
514                 "created_by": {
515                   "id": 1,
516                   "username": "admin",
517                   "first_name": "",
518                   "last_name": ""
519                 },
520                 "modified_by": {
521                   "id": 1,
522                   "username": "admin",
523                   "first_name": "",
524                   "last_name": ""
525                 },
526                 "object_roles": {
527                   "admin_role": {
528                     "description": "Can manage all aspects of the inventory",
529                     "name": "Admin",
530                     "id": 21
531                   },
532                   "update_role": {
533                     "description": "May update project or inventory or group using the configured source update system",
534                     "name": "Update",
535                     "id": 22
536                   },
537                   "adhoc_role": {
538                     "description": "May run ad hoc commands on an inventory",
539                     "name": "Ad Hoc",
540                     "id": 23
541                   },
542                   "use_role": {
543                     "description": "Can use the inventory in a job template",
544                     "name": "Use",
545                     "id": 24
546                   },
547                   "read_role": {
548                     "description": "May view settings for the inventory",
549                     "name": "Read",
550                     "id": 25
551                   }
552                 },
553                 "user_capabilities": {
554                   "edit": true,
555                   "delete": true,
556                   "copy": true,
557                   "adhoc": true
558                 }
559               },
560               "created": "2019-05-21T15:45:31.954359Z",
561               "modified": "2019-05-21T15:45:31.954378Z",
562               "name": "Demo Inventory",
563               "description": "",
564               "organization": 1,
565               "kind": "",
566               "host_filter": null,
567               "variables": "",
568               "has_active_failures": false,
569               "total_hosts": 1,
570               "hosts_with_active_failures": 0,
571               "total_groups": 0,
572               "groups_with_active_failures": 0,
573               "has_inventory_sources": false,
574               "total_inventory_sources": 0,
575               "inventory_sources_with_failures": 0,
576               "insights_credential": null,
577               "pending_deletion": false
578             }
579           ]
580         }"""
581
582     private fun newJobTemplateLaunch(jtId: Int, jobId: Int) = """{
583       "job": $jobId,
584       "ignored_fields": {},
585       "id": $jobId,
586       "type": "job",
587       "url": "/api/v2/jobs/$jobId/",
588       "related": {
589         "created_by": "/api/v2/users/1/",
590         "modified_by": "/api/v2/users/1/",
591         "labels": "/api/v2/jobs/$jobId/labels/",
592         "inventory": "/api/v2/inventories/1/",
593         "project": "/api/v2/projects/8/",
594         "extra_credentials": "/api/v2/jobs/$jobId/extra_credentials/",
595         "credentials": "/api/v2/jobs/$jobId/credentials/",
596         "unified_job_template": "/api/v2/job_templates/$jtId/",
597         "stdout": "/api/v2/jobs/$jobId/stdout/",
598         "job_events": "/api/v2/jobs/$jobId/job_events/",
599         "job_host_summaries": "/api/v2/jobs/$jobId/job_host_summaries/",
600         "activity_stream": "/api/v2/jobs/$jobId/activity_stream/",
601         "notifications": "/api/v2/jobs/$jobId/notifications/",
602         "job_template": "/api/v2/job_templates/$jtId/",
603         "cancel": "/api/v2/jobs/$jobId/cancel/",
604         "create_schedule": "/api/v2/jobs/$jobId/create_schedule/",
605         "relaunch": "/api/v2/jobs/$jobId/relaunch/"
606       },
607       "summary_fields": {
608         "inventory": {
609           "id": 1,
610           "name": "Demo Inventory",
611           "description": "",
612           "has_active_failures": false,
613           "total_hosts": 1,
614           "hosts_with_active_failures": 0,
615           "total_groups": 0,
616           "groups_with_active_failures": 0,
617           "has_inventory_sources": false,
618           "total_inventory_sources": 0,
619           "inventory_sources_with_failures": 0,
620           "organization_id": 1,
621           "kind": ""
622         },
623         "project": {
624           "id": 8,
625           "name": "cds_playbooks",
626           "description": "CDS - cds_playbooks Project",
627           "status": "ok",
628           "scm_type": ""
629         },
630         "job_template": {
631           "id": $jtId,
632           "name": "hello_world_job_template",
633           "description": "hello_world Runner Job Template"
634         },
635         "unified_job_template": {
636           "id": $jtId,
637           "name": "hello_world_job_template",
638           "description": "hello_world Runner Job Template",
639           "unified_job_type": "job"
640         },
641         "created_by": {
642           "id": 1,
643           "username": "admin",
644           "first_name": "",
645           "last_name": ""
646         },
647         "modified_by": {
648           "id": 1,
649           "username": "admin",
650           "first_name": "",
651           "last_name": ""
652         },
653         "user_capabilities": {
654           "delete": true,
655           "start": true
656         },
657         "labels": {
658           "count": 0,
659           "results": []
660         },
661         "extra_credentials": [],
662         "credentials": []
663       },
664       "created": "2019-06-12T11:21:26.891986Z",
665       "modified": "2019-06-12T11:21:27.016410Z",
666       "name": "hello_world_job_template",
667       "description": "hello_world Runner Job Template",
668       "job_type": "run",
669       "inventory": 1,
670       "project": 8,
671       "playbook": "hello_world.yml",
672       "forks": 0,
673       "limit": "",
674       "verbosity": 0,
675       "extra_vars": "{\"tor_group\": \"vEPC\", \"site_id\": \"3 - Belmont\"}",
676       "job_tags": "",
677       "force_handlers": false,
678       "skip_tags": "",
679       "start_at_task": "",
680       "timeout": 0,
681       "use_fact_cache": false,
682       "unified_job_template": $jtId,
683       "launch_type": "manual",
684       "status": "pending",
685       "failed": false,
686       "started": null,
687       "finished": null,
688       "elapsed": 0,
689       "job_args": "",
690       "job_cwd": "",
691       "job_env": {},
692       "job_explanation": "",
693       "execution_node": "",
694       "controller_node": "",
695       "result_traceback": "",
696       "event_processing_finished": false,
697       "job_template": $jtId,
698       "passwords_needed_to_start": [],
699       "ask_diff_mode_on_launch": false,
700       "ask_variables_on_launch": true,
701       "ask_limit_on_launch": true,
702       "ask_tags_on_launch": true,
703       "ask_skip_tags_on_launch": true,
704       "ask_job_type_on_launch": false,
705       "ask_verbosity_on_launch": false,
706       "ask_inventory_on_launch": true,
707       "ask_credential_on_launch": true,
708       "allow_simultaneous": false,
709       "artifacts": {},
710       "scm_revision": "",
711       "instance_group": null,
712       "diff_mode": false,
713       "job_slice_number": 0,
714       "job_slice_count": 1,
715       "credential": null,
716       "vault_credential": null
717     }"""
718
719     private fun getJobStatus1(jtId: Int, jobId: Int) = """{
720       "id": $jobId,
721       "type": "job",
722       "url": "/api/v2/jobs/$jobId/",
723       "related": {
724         "created_by": "/api/v2/users/1/",
725         "labels": "/api/v2/jobs/$jobId/labels/",
726         "inventory": "/api/v2/inventories/1/",
727         "project": "/api/v2/projects/8/",
728         "extra_credentials": "/api/v2/jobs/$jobId/extra_credentials/",
729         "credentials": "/api/v2/jobs/$jobId/credentials/",
730         "unified_job_template": "/api/v2/job_templates/$jtId/",
731         "stdout": "/api/v2/jobs/$jobId/stdout/",
732         "job_events": "/api/v2/jobs/$jobId/job_events/",
733         "job_host_summaries": "/api/v2/jobs/$jobId/job_host_summaries/",
734         "activity_stream": "/api/v2/jobs/$jobId/activity_stream/",
735         "notifications": "/api/v2/jobs/$jobId/notifications/",
736         "job_template": "/api/v2/job_templates/$jtId/",
737         "cancel": "/api/v2/jobs/$jobId/cancel/",
738         "create_schedule": "/api/v2/jobs/$jobId/create_schedule/",
739         "relaunch": "/api/v2/jobs/$jobId/relaunch/"
740       },
741       "summary_fields": {
742         "inventory": {
743           "id": 1,
744           "name": "Demo Inventory",
745           "description": "",
746           "has_active_failures": false,
747           "total_hosts": 1,
748           "hosts_with_active_failures": 0,
749           "total_groups": 0,
750           "groups_with_active_failures": 0,
751           "has_inventory_sources": false,
752           "total_inventory_sources": 0,
753           "inventory_sources_with_failures": 0,
754           "organization_id": 1,
755           "kind": ""
756         },
757         "project": {
758           "id": 8,
759           "name": "cds_playbooks",
760           "description": "CDS - cds_playbooks Project",
761           "status": "ok",
762           "scm_type": ""
763         },
764         "job_template": {
765           "id": $jtId,
766           "name": "hello_world_job_template",
767           "description": "hello_world Runner Job Template"
768         },
769         "unified_job_template": {
770           "id": $jtId,
771           "name": "hello_world_job_template",
772           "description": "hello_world Runner Job Template",
773           "unified_job_type": "job"
774         },
775         "instance_group": {
776           "name": "tower",
777           "id": 1
778         },
779         "created_by": {
780           "id": 1,
781           "username": "admin",
782           "first_name": "",
783           "last_name": ""
784         },
785         "user_capabilities": {
786           "delete": true,
787           "start": true
788         },
789         "labels": {
790           "count": 0,
791           "results": []
792         },
793         "extra_credentials": [],
794         "credentials": []
795       },
796       "created": "2019-06-12T11:21:26.891986Z",
797       "modified": "2019-06-12T11:21:27.355185Z",
798       "name": "hello_world_job_template",
799       "description": "hello_world Runner Job Template",
800       "job_type": "run",
801       "inventory": 1,
802       "project": 8,
803       "playbook": "hello_world.yml",
804       "forks": 0,
805       "limit": "",
806       "verbosity": 0,
807       "extra_vars": "{\"tor_group\": \"vEPC\", \"site_id\": \"3 - Belmont\"}",
808       "job_tags": "",
809       "force_handlers": false,
810       "skip_tags": "",
811       "start_at_task": "",
812       "timeout": 0,
813       "use_fact_cache": false,
814       "unified_job_template": $jtId,
815       "launch_type": "manual",
816       "status": "waiting",
817       "failed": false,
818       "started": null,
819       "finished": null,
820       "elapsed": 0,
821       "job_args": "",
822       "job_cwd": "",
823       "job_env": {},
824       "job_explanation": "",
825       "execution_node": "awx",
826       "controller_node": "",
827       "result_traceback": "",
828       "event_processing_finished": false,
829       "job_template": $jtId,
830       "passwords_needed_to_start": [],
831       "ask_diff_mode_on_launch": false,
832       "ask_variables_on_launch": true,
833       "ask_limit_on_launch": true,
834       "ask_tags_on_launch": true,
835       "ask_skip_tags_on_launch": true,
836       "ask_job_type_on_launch": false,
837       "ask_verbosity_on_launch": false,
838       "ask_inventory_on_launch": true,
839       "ask_credential_on_launch": true,
840       "allow_simultaneous": false,
841       "artifacts": {},
842       "scm_revision": "",
843       "instance_group": 1,
844       "diff_mode": false,
845       "job_slice_number": 0,
846       "job_slice_count": 1,
847       "host_status_counts": {},
848       "playbook_counts": {
849         "play_count": 0,
850         "task_count": 0
851       },
852       "custom_virtualenv": null,
853       "credential": null,
854       "vault_credential": null
855     }"""
856
857     private fun getJobStatus2(jtId: Int, jobId: Int) = """{
858       "id": $jobId,
859       "type": "job",
860       "url": "/api/v2/jobs/$jobId/",
861       "related": {
862         "created_by": "/api/v2/users/1/",
863         "labels": "/api/v2/jobs/$jobId/labels/",
864         "inventory": "/api/v2/inventories/1/",
865         "project": "/api/v2/projects/8/",
866         "extra_credentials": "/api/v2/jobs/$jobId/extra_credentials/",
867         "credentials": "/api/v2/jobs/$jobId/credentials/",
868         "unified_job_template": "/api/v2/job_templates/$jtId/",
869         "stdout": "/api/v2/jobs/$jobId/stdout/",
870         "job_events": "/api/v2/jobs/$jobId/job_events/",
871         "job_host_summaries": "/api/v2/jobs/$jobId/job_host_summaries/",
872         "activity_stream": "/api/v2/jobs/$jobId/activity_stream/",
873         "notifications": "/api/v2/jobs/$jobId/notifications/",
874         "job_template": "/api/v2/job_templates/$jtId/",
875         "cancel": "/api/v2/jobs/$jobId/cancel/",
876         "create_schedule": "/api/v2/jobs/$jobId/create_schedule/",
877         "relaunch": "/api/v2/jobs/$jobId/relaunch/"
878       },
879       "summary_fields": {
880         "inventory": {
881           "id": 1,
882           "name": "Demo Inventory",
883           "description": "",
884           "has_active_failures": false,
885           "total_hosts": 1,
886           "hosts_with_active_failures": 0,
887           "total_groups": 0,
888           "groups_with_active_failures": 0,
889           "has_inventory_sources": false,
890           "total_inventory_sources": 0,
891           "inventory_sources_with_failures": 0,
892           "organization_id": 1,
893           "kind": ""
894         },
895         "project": {
896           "id": 8,
897           "name": "cds_playbooks",
898           "description": "CDS - cds_playbooks Project",
899           "status": "ok",
900           "scm_type": ""
901         },
902         "job_template": {
903           "id": $jtId,
904           "name": "hello_world_job_template",
905           "description": "hello_world Runner Job Template"
906         },
907         "unified_job_template": {
908           "id": $jtId,
909           "name": "hello_world_job_template",
910           "description": "hello_world Runner Job Template",
911           "unified_job_type": "job"
912         },
913         "instance_group": {
914           "name": "tower",
915           "id": 1
916         },
917         "created_by": {
918           "id": 1,
919           "username": "admin",
920           "first_name": "",
921           "last_name": ""
922         },
923         "user_capabilities": {
924           "delete": true,
925           "start": true
926         },
927         "labels": {
928           "count": 0,
929           "results": []
930         },
931         "extra_credentials": [],
932         "credentials": []
933       },
934       "created": "2019-06-12T11:21:26.891986Z",
935       "modified": "2019-06-12T11:21:27.355185Z",
936       "name": "hello_world_job_template",
937       "description": "hello_world Runner Job Template",
938       "job_type": "run",
939       "inventory": 1,
940       "project": 8,
941       "playbook": "hello_world.yml",
942       "forks": 0,
943       "limit": "",
944       "verbosity": 0,
945       "extra_vars": "{\"tor_group\": \"vEPC\", \"site_id\": \"3 - Belmont\"}",
946       "job_tags": "",
947       "force_handlers": false,
948       "skip_tags": "",
949       "start_at_task": "",
950       "timeout": 0,
951       "use_fact_cache": false,
952       "unified_job_template": $jtId,
953       "launch_type": "manual",
954       "status": "running",
955       "failed": false,
956       "started": "2019-06-12T11:21:27.510766Z",
957       "finished": null,
958       "elapsed": 10.862184,
959       "job_args": "[\"ansible-playbook\", \"-u\", \"root\", \"-i\", \"/tmp/awx_223_ft8hu4p4/tmptmtwllu4\", \"-e\", \"@/tmp/awx_223_ft8hu4p4/env/extravars\", \"hello_world.yml\"]",
960       "job_cwd": "/var/lib/awx/projects/cds_playbooks_folder",
961       "job_env": {
962         "HOSTNAME": "awx",
963         "LC_ALL": "en_US.UTF-8",
964         "VIRTUAL_ENV": "/var/lib/awx/venv/ansible",
965         "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",
966         "SUPERVISOR_GROUP_NAME": "tower-processes",
967         "PWD": "/var/lib/awx",
968         "LANG": "en_US.UTF-8",
969         "PS1": "(awx) ",
970         "SUPERVISOR_ENABLED": "1",
971         "HOME": "/var/lib/awx",
972         "SHLVL": "2",
973         "LANGUAGE": "en_US.UTF-8",
974         "LC_CTYPE": "en_US.UTF-8",
975         "SUPERVISOR_PROCESS_NAME": "dispatcher",
976         "SUPERVISOR_SERVER_URL": "unix:///tmp/supervisor.sock",
977         "DJANGO_SETTINGS_MODULE": "awx.settings.production",
978         "DJANGO_LIVE_TEST_SERVER_ADDRESS": "localhost:9013-9199",
979         "TZ": "UTC",
980         "ANSIBLE_FORCE_COLOR": "True",
981         "ANSIBLE_HOST_KEY_CHECKING": "False",
982         "ANSIBLE_INVENTORY_UNPARSED_FAILED": "True",
983         "ANSIBLE_PARAMIKO_RECORD_HOST_KEYS": "False",
984         "ANSIBLE_VENV_PATH": "/var/lib/awx/venv/ansible",
985         "AWX_PRIVATE_DATA_DIR": "/tmp/awx_223_ft8hu4p4",
986         "PYTHONPATH": "/var/lib/awx/venv/ansible/lib/python2.7/site-packages:/var/lib/awx/venv/awx/lib64/python3.6/site-packages/awx/lib:",
987         "JOB_ID": "$jobId",
988         "INVENTORY_ID": "1",
989         "PROJECT_REVISION": "",
990         "ANSIBLE_RETRY_FILES_ENABLED": "False",
991         "MAX_EVENT_RES": "700000",
992         "ANSIBLE_CALLBACK_PLUGINS": "/var/lib/awx/venv/awx/lib64/python3.6/site-packages/awx/plugins/callback",
993         "AWX_HOST": "https://towerhost",
994         "ANSIBLE_SSH_CONTROL_PATH_DIR": "/tmp/awx_223_ft8hu4p4/cp",
995         "ANSIBLE_STDOUT_CALLBACK": "awx_display",
996         "AWX_ISOLATED_DATA_DIR": "/tmp/awx_223_ft8hu4p4/artifacts/$jobId"
997       },
998       "job_explanation": "",
999       "execution_node": "awx",
1000       "controller_node": "",
1001       "result_traceback": "",
1002       "event_processing_finished": false,
1003       "job_template": $jtId,
1004       "passwords_needed_to_start": [],
1005       "ask_diff_mode_on_launch": false,
1006       "ask_variables_on_launch": true,
1007       "ask_limit_on_launch": true,
1008       "ask_tags_on_launch": true,
1009       "ask_skip_tags_on_launch": true,
1010       "ask_job_type_on_launch": false,
1011       "ask_verbosity_on_launch": false,
1012       "ask_inventory_on_launch": true,
1013       "ask_credential_on_launch": true,
1014       "allow_simultaneous": false,
1015       "artifacts": {},
1016       "scm_revision": "",
1017       "instance_group": 1,
1018       "diff_mode": false,
1019       "job_slice_number": 0,
1020       "job_slice_count": 1,
1021       "host_status_counts": {},
1022       "playbook_counts": {
1023         "play_count": 1,
1024         "task_count": 1
1025       },
1026       "custom_virtualenv": "/var/lib/awx/venv/ansible",
1027       "credential": null,
1028       "vault_credential": null
1029     }"""
1030
1031     private fun getJobStatus3(jtId: Int, jobId: Int) = """{
1032       "id": $jobId,
1033       "type": "job",
1034       "url": "/api/v2/jobs/$jobId/",
1035       "related": {
1036         "created_by": "/api/v2/users/1/",
1037         "labels": "/api/v2/jobs/$jobId/labels/",
1038         "inventory": "/api/v2/inventories/1/",
1039         "project": "/api/v2/projects/8/",
1040         "extra_credentials": "/api/v2/jobs/$jobId/extra_credentials/",
1041         "credentials": "/api/v2/jobs/$jobId/credentials/",
1042         "unified_job_template": "/api/v2/job_templates/$jtId/",
1043         "stdout": "/api/v2/jobs/$jobId/stdout/",
1044         "job_events": "/api/v2/jobs/$jobId/job_events/",
1045         "job_host_summaries": "/api/v2/jobs/$jobId/job_host_summaries/",
1046         "activity_stream": "/api/v2/jobs/$jobId/activity_stream/",
1047         "notifications": "/api/v2/jobs/$jobId/notifications/",
1048         "job_template": "/api/v2/job_templates/$jtId/",
1049         "cancel": "/api/v2/jobs/$jobId/cancel/",
1050         "create_schedule": "/api/v2/jobs/$jobId/create_schedule/",
1051         "relaunch": "/api/v2/jobs/$jobId/relaunch/"
1052       },
1053       "summary_fields": {
1054         "inventory": {
1055           "id": 1,
1056           "name": "Demo Inventory",
1057           "description": "",
1058           "has_active_failures": false,
1059           "total_hosts": 1,
1060           "hosts_with_active_failures": 0,
1061           "total_groups": 0,
1062           "groups_with_active_failures": 0,
1063           "has_inventory_sources": false,
1064           "total_inventory_sources": 0,
1065           "inventory_sources_with_failures": 0,
1066           "organization_id": 1,
1067           "kind": ""
1068         },
1069         "project": {
1070           "id": 8,
1071           "name": "cds_playbooks",
1072           "description": "CDS - cds_playbooks Project",
1073           "status": "ok",
1074           "scm_type": ""
1075         },
1076         "job_template": {
1077           "id": $jtId,
1078           "name": "hello_world_job_template",
1079           "description": "hello_world Runner Job Template"
1080         },
1081         "unified_job_template": {
1082           "id": $jtId,
1083           "name": "hello_world_job_template",
1084           "description": "hello_world Runner Job Template",
1085           "unified_job_type": "job"
1086         },
1087         "instance_group": {
1088           "name": "tower",
1089           "id": 1
1090         },
1091         "created_by": {
1092           "id": 1,
1093           "username": "admin",
1094           "first_name": "",
1095           "last_name": ""
1096         },
1097         "user_capabilities": {
1098           "delete": true,
1099           "start": true
1100         },
1101         "labels": {
1102           "count": 0,
1103           "results": []
1104         },
1105         "extra_credentials": [],
1106         "credentials": []
1107       },
1108       "created": "2019-06-12T11:21:26.891986Z",
1109       "modified": "2019-06-12T11:21:27.355185Z",
1110       "name": "hello_world_job_template",
1111       "description": "hello_world Runner Job Template",
1112       "job_type": "run",
1113       "inventory": 1,
1114       "project": 8,
1115       "playbook": "hello_world.yml",
1116       "forks": 0,
1117       "limit": "",
1118       "verbosity": 0,
1119       "extra_vars": "{\"tor_group\": \"vEPC\", \"site_id\": \"3 - Belmont\"}",
1120       "job_tags": "",
1121       "force_handlers": false,
1122       "skip_tags": "",
1123       "start_at_task": "",
1124       "timeout": 0,
1125       "use_fact_cache": false,
1126       "unified_job_template": $jtId,
1127       "launch_type": "manual",
1128       "status": "running",
1129       "failed": false,
1130       "started": "2019-06-12T11:21:27.510766Z",
1131       "finished": null,
1132       "elapsed": 21.297881,
1133       "job_args": "[\"ansible-playbook\", \"-u\", \"root\", \"-i\", \"/tmp/awx_223_ft8hu4p4/tmptmtwllu4\", \"-e\", \"@/tmp/awx_223_ft8hu4p4/env/extravars\", \"hello_world.yml\"]",
1134       "job_cwd": "/var/lib/awx/projects/cds_playbooks_folder",
1135       "job_env": {
1136         "HOSTNAME": "awx",
1137         "LC_ALL": "en_US.UTF-8",
1138         "VIRTUAL_ENV": "/var/lib/awx/venv/ansible",
1139         "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",
1140         "SUPERVISOR_GROUP_NAME": "tower-processes",
1141         "PWD": "/var/lib/awx",
1142         "LANG": "en_US.UTF-8",
1143         "PS1": "(awx) ",
1144         "SUPERVISOR_ENABLED": "1",
1145         "HOME": "/var/lib/awx",
1146         "SHLVL": "2",
1147         "LANGUAGE": "en_US.UTF-8",
1148         "LC_CTYPE": "en_US.UTF-8",
1149         "SUPERVISOR_PROCESS_NAME": "dispatcher",
1150         "SUPERVISOR_SERVER_URL": "unix:///tmp/supervisor.sock",
1151         "DJANGO_SETTINGS_MODULE": "awx.settings.production",
1152         "DJANGO_LIVE_TEST_SERVER_ADDRESS": "localhost:9013-9199",
1153         "TZ": "UTC",
1154         "ANSIBLE_FORCE_COLOR": "True",
1155         "ANSIBLE_HOST_KEY_CHECKING": "False",
1156         "ANSIBLE_INVENTORY_UNPARSED_FAILED": "True",
1157         "ANSIBLE_PARAMIKO_RECORD_HOST_KEYS": "False",
1158         "ANSIBLE_VENV_PATH": "/var/lib/awx/venv/ansible",
1159         "AWX_PRIVATE_DATA_DIR": "/tmp/awx_223_ft8hu4p4",
1160         "PYTHONPATH": "/var/lib/awx/venv/ansible/lib/python2.7/site-packages:/var/lib/awx/venv/awx/lib64/python3.6/site-packages/awx/lib:",
1161         "JOB_ID": "$jobId",
1162         "INVENTORY_ID": "1",
1163         "PROJECT_REVISION": "",
1164         "ANSIBLE_RETRY_FILES_ENABLED": "False",
1165         "MAX_EVENT_RES": "700000",
1166         "ANSIBLE_CALLBACK_PLUGINS": "/var/lib/awx/venv/awx/lib64/python3.6/site-packages/awx/plugins/callback",
1167         "AWX_HOST": "https://towerhost",
1168         "ANSIBLE_SSH_CONTROL_PATH_DIR": "/tmp/awx_223_ft8hu4p4/cp",
1169         "ANSIBLE_STDOUT_CALLBACK": "awx_display",
1170         "AWX_ISOLATED_DATA_DIR": "/tmp/awx_223_ft8hu4p4/artifacts/$jobId"
1171       },
1172       "job_explanation": "",
1173       "execution_node": "awx",
1174       "controller_node": "",
1175       "result_traceback": "",
1176       "event_processing_finished": false,
1177       "job_template": $jtId,
1178       "passwords_needed_to_start": [],
1179       "ask_diff_mode_on_launch": false,
1180       "ask_variables_on_launch": true,
1181       "ask_limit_on_launch": true,
1182       "ask_tags_on_launch": true,
1183       "ask_skip_tags_on_launch": true,
1184       "ask_job_type_on_launch": false,
1185       "ask_verbosity_on_launch": false,
1186       "ask_inventory_on_launch": true,
1187       "ask_credential_on_launch": true,
1188       "allow_simultaneous": false,
1189       "artifacts": {},
1190       "scm_revision": "",
1191       "instance_group": 1,
1192       "diff_mode": false,
1193       "job_slice_number": 0,
1194       "job_slice_count": 1,
1195       "host_status_counts": {},
1196       "playbook_counts": {
1197         "play_count": 1,
1198         "task_count": 2
1199       },
1200       "custom_virtualenv": "/var/lib/awx/venv/ansible",
1201       "credential": null,
1202       "vault_credential": null
1203     } """
1204
1205     private fun getJobStatus4(jtId: Int, jobId: Int) = """{
1206       "id": $jobId,
1207       "type": "job",
1208       "url": "/api/v2/jobs/$jobId/",
1209       "related": {
1210         "created_by": "/api/v2/users/1/",
1211         "labels": "/api/v2/jobs/$jobId/labels/",
1212         "inventory": "/api/v2/inventories/1/",
1213         "project": "/api/v2/projects/8/",
1214         "extra_credentials": "/api/v2/jobs/$jobId/extra_credentials/",
1215         "credentials": "/api/v2/jobs/$jobId/credentials/",
1216         "unified_job_template": "/api/v2/job_templates/$jtId/",
1217         "stdout": "/api/v2/jobs/$jobId/stdout/",
1218         "job_events": "/api/v2/jobs/$jobId/job_events/",
1219         "job_host_summaries": "/api/v2/jobs/$jobId/job_host_summaries/",
1220         "activity_stream": "/api/v2/jobs/$jobId/activity_stream/",
1221         "notifications": "/api/v2/jobs/$jobId/notifications/",
1222         "job_template": "/api/v2/job_templates/$jtId/",
1223         "cancel": "/api/v2/jobs/$jobId/cancel/",
1224         "create_schedule": "/api/v2/jobs/$jobId/create_schedule/",
1225         "relaunch": "/api/v2/jobs/$jobId/relaunch/"
1226       },
1227       "summary_fields": {
1228         "inventory": {
1229           "id": 1,
1230           "name": "Demo Inventory",
1231           "description": "",
1232           "has_active_failures": false,
1233           "total_hosts": 1,
1234           "hosts_with_active_failures": 0,
1235           "total_groups": 0,
1236           "groups_with_active_failures": 0,
1237           "has_inventory_sources": false,
1238           "total_inventory_sources": 0,
1239           "inventory_sources_with_failures": 0,
1240           "organization_id": 1,
1241           "kind": ""
1242         },
1243         "project": {
1244           "id": 8,
1245           "name": "cds_playbooks",
1246           "description": "CDS - cds_playbooks Project",
1247           "status": "ok",
1248           "scm_type": ""
1249         },
1250         "job_template": {
1251           "id": $jtId,
1252           "name": "hello_world_job_template",
1253           "description": "hello_world Runner Job Template"
1254         },
1255         "unified_job_template": {
1256           "id": $jtId,
1257           "name": "hello_world_job_template",
1258           "description": "hello_world Runner Job Template",
1259           "unified_job_type": "job"
1260         },
1261         "instance_group": {
1262           "name": "tower",
1263           "id": 1
1264         },
1265         "created_by": {
1266           "id": 1,
1267           "username": "admin",
1268           "first_name": "",
1269           "last_name": ""
1270         },
1271         "user_capabilities": {
1272           "delete": true,
1273           "start": true
1274         },
1275         "labels": {
1276           "count": 0,
1277           "results": []
1278         },
1279         "extra_credentials": [],
1280         "credentials": []
1281       },
1282       "created": "2019-06-12T11:21:26.891986Z",
1283       "modified": "2019-06-12T11:21:27.355185Z",
1284       "name": "hello_world_job_template",
1285       "description": "hello_world Runner Job Template",
1286       "job_type": "run",
1287       "inventory": 1,
1288       "project": 8,
1289       "playbook": "hello_world.yml",
1290       "forks": 0,
1291       "limit": "",
1292       "verbosity": 0,
1293       "extra_vars": "{\"tor_group\": \"vEPC\", \"site_id\": \"3 - Belmont\"}",
1294       "job_tags": "",
1295       "force_handlers": false,
1296       "skip_tags": "",
1297       "start_at_task": "",
1298       "timeout": 0,
1299       "use_fact_cache": false,
1300       "unified_job_template": $jtId,
1301       "launch_type": "manual",
1302       "status": "successful",
1303       "failed": false,
1304       "started": "2019-06-12T11:21:27.510766Z",
1305       "finished": "2019-06-12T11:21:48.993385Z",
1306       "elapsed": 21.483,
1307       "job_args": "[\"ansible-playbook\", \"-u\", \"root\", \"-i\", \"/tmp/awx_223_ft8hu4p4/tmptmtwllu4\", \"-e\", \"@/tmp/awx_223_ft8hu4p4/env/extravars\", \"hello_world.yml\"]",
1308       "job_cwd": "/var/lib/awx/projects/cds_playbooks_folder",
1309       "job_env": {
1310         "HOSTNAME": "awx",
1311         "LC_ALL": "en_US.UTF-8",
1312         "VIRTUAL_ENV": "/var/lib/awx/venv/ansible",
1313         "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",
1314         "SUPERVISOR_GROUP_NAME": "tower-processes",
1315         "PWD": "/var/lib/awx",
1316         "LANG": "en_US.UTF-8",
1317         "PS1": "(awx) ",
1318         "SUPERVISOR_ENABLED": "1",
1319         "HOME": "/var/lib/awx",
1320         "SHLVL": "2",
1321         "LANGUAGE": "en_US.UTF-8",
1322         "LC_CTYPE": "en_US.UTF-8",
1323         "SUPERVISOR_PROCESS_NAME": "dispatcher",
1324         "SUPERVISOR_SERVER_URL": "unix:///tmp/supervisor.sock",
1325         "DJANGO_SETTINGS_MODULE": "awx.settings.production",
1326         "DJANGO_LIVE_TEST_SERVER_ADDRESS": "localhost:9013-9199",
1327         "TZ": "UTC",
1328         "ANSIBLE_FORCE_COLOR": "True",
1329         "ANSIBLE_HOST_KEY_CHECKING": "False",
1330         "ANSIBLE_INVENTORY_UNPARSED_FAILED": "True",
1331         "ANSIBLE_PARAMIKO_RECORD_HOST_KEYS": "False",
1332         "ANSIBLE_VENV_PATH": "/var/lib/awx/venv/ansible",
1333         "AWX_PRIVATE_DATA_DIR": "/tmp/awx_223_ft8hu4p4",
1334         "PYTHONPATH": "/var/lib/awx/venv/ansible/lib/python2.7/site-packages:/var/lib/awx/venv/awx/lib64/python3.6/site-packages/awx/lib:",
1335         "JOB_ID": "$jobId",
1336         "INVENTORY_ID": "1",
1337         "PROJECT_REVISION": "",
1338         "ANSIBLE_RETRY_FILES_ENABLED": "False",
1339         "MAX_EVENT_RES": "700000",
1340         "ANSIBLE_CALLBACK_PLUGINS": "/var/lib/awx/venv/awx/lib64/python3.6/site-packages/awx/plugins/callback",
1341         "AWX_HOST": "https://towerhost",
1342         "ANSIBLE_SSH_CONTROL_PATH_DIR": "/tmp/awx_223_ft8hu4p4/cp",
1343         "ANSIBLE_STDOUT_CALLBACK": "awx_display",
1344         "AWX_ISOLATED_DATA_DIR": "/tmp/awx_223_ft8hu4p4/artifacts/$jobId"
1345       },
1346       "job_explanation": "",
1347       "execution_node": "awx",
1348       "controller_node": "",
1349       "result_traceback": "",
1350       "event_processing_finished": true,
1351       "job_template": $jtId,
1352       "passwords_needed_to_start": [],
1353       "ask_diff_mode_on_launch": false,
1354       "ask_variables_on_launch": true,
1355       "ask_limit_on_launch": true,
1356       "ask_tags_on_launch": true,
1357       "ask_skip_tags_on_launch": true,
1358       "ask_job_type_on_launch": false,
1359       "ask_verbosity_on_launch": false,
1360       "ask_inventory_on_launch": true,
1361       "ask_credential_on_launch": true,
1362       "allow_simultaneous": false,
1363       "artifacts": {},
1364       "scm_revision": "",
1365       "instance_group": 1,
1366       "diff_mode": false,
1367       "job_slice_number": 0,
1368       "job_slice_count": 1,
1369       "host_status_counts": {
1370         "ok": 1
1371       },
1372       "playbook_counts": {
1373         "play_count": 1,
1374         "task_count": 2
1375       },
1376       "custom_virtualenv": "/var/lib/awx/venv/ansible",
1377       "credential": null,
1378       "vault_credential": null
1379     }"""
1380
1381     private fun getReport() = """
1382
1383 PLAY [Hello World Sample] ******************************************************
1384
1385 TASK [Gathering Facts] *********************************************************
1386 ok: [localhost]
1387
1388 TASK [Hello Message] ***********************************************************
1389 ok: [localhost] => {
1390     "msg": "Hello World!"
1391 }
1392
1393 PLAY RECAP *********************************************************************
1394 localhost                  : ok=2    changed=0    unreachable=0    failed=0
1395
1396 """
1397 }