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