Introduction
AWX provides a REST API which allows to do pretty all commands that can be executed through the web interface, using http requests.
Sometimes is more easy to restart, or start jobs for instance through API, instead of going through the graphical interface.
First access of REST API
For instance, suppose the AWX server IP is 127.0.0.1
.
Get some basic AWX server informations:
awxtest> curl -X GET -k https://127.0.0.1/api/ | jq .
{
"description": "AWX REST API",
"current_version": "/api/v2/",
"available_versions": {
"v2": "/api/v2/"
},
"oauth2": "/api/o/",
"custom_logo": "",
"custom_login_info": "",
"login_redirect_override": ""
}
So the path to the API is /api/v2/
(checkout "v2": "/api/v2/"
line)
Let’s get the list of all endpoints available:
awxtest> curl -X GET -k https://127.0.0.1/api/v2/ | jq .
{
"ping": "/api/v2/ping/",
"instances": "/api/v2/instances/",
"instance_groups": "/api/v2/instance_groups/",
"config": "/api/v2/config/",
"settings": "/api/v2/settings/",
....
}
NOTE: I used jq
to have a pretty print the JSON in a terminal. But is not necessary. Just nice to have.
How to list all jobs:
awxtest> curl -X GET --user admin:myadminpassword -k https://127.0.0.1/api/v2/job_templates/ | jq .
¨
{
"id": 7,
"type": "job_template",
"url": "/api/v2/job_templates/7/",
"related": {
"named_url": "/api/v2/job_templates/Demo Job Template++Default/",
"created_by": "/api/v2/users/1/",
"modified_by": "/api/v2/users/1/",
"labels": "/api/v2/job_templates/7/labels/",
"inventory": "/api/v2/inventories/1/",
"project": "/api/v2/projects/6/",
"organization": "/api/v2/organizations/1/",
"credentials": "/api/v2/job_templates/7/credentials/",
"last_job": "/api/v2/jobs/2/",
"jobs": "/api/v2/job_templates/7/jobs/",
"schedules": "/api/v2/job_templates/7/schedules/",
"activity_stream": "/api/v2/job_templates/7/activity_stream/",
"launch": "/api/v2/job_templates/7/launch/",
"webhook_key": "/api/v2/job_templates/7/webhook_key/",
"webhook_receiver": "",
"notification_templates_started": "/api/v2/job_templates/7/notification_templates_started/",
"notification_templates_success": "/api/v2/job_templates/7/notification_templates_success/",
"notification_templates_error": "/api/v2/job_templates/7/notification_templates_error/",
"access_list": "/api/v2/job_templates/7/access_list/",
"survey_spec": "/api/v2/job_templates/7/survey_spec/",
"object_roles": "/api/v2/job_templates/7/object_roles/",
"instance_groups": "/api/v2/job_templates/7/instance_groups/",
"slice_workflow_jobs": "/api/v2/job_templates/7/slice_workflow_jobs/",
"copy": "/api/v2/job_templates/7/copy/"
There are pretty a lot of information here about the jobs, and also the endpoints to access these tasks.
In order to launch a job use the launch
key: "launch": "/api/v2/job_templates/7/launch/"
which gives you the URI to use to launch the job number 7.
Let’s get the job id to start the job.
awxtest> curl -X POST --user admin:myadminpassword -k https://127.0.0.1/api/v2/job_templates/7/launch/ | jq .
...
"verbosity" : 0,
"extra_vars" : "{}",
"job" : 72,
"created" : "2018-11-20T11:09:49.813893Z", "force_handlers" : false,
...
Here the job id is 72.
Start the job:
awxtest> curl -X GET --user admin:myadminpassword https://127.0.0.1/api/v2/jobs/72/ -k -s | jq .
Putting all together
Lets create an Ansible playbook to do all these steps in one.
---
- name: Tower API
hosts: localhost
become: false
vars:
tower_user: admin
tower_pass: myadminpassword
tower_host: 127.0.0.1
tower_job_id: 7
tasks:
- name: Launch a new Job
uri:
url: https://{{ tower_host }}/api/v2/job_templates/{{ tower_job_id }}/launch/
method: POST
validate_certs: no
return_content: yes
user: "{{ tower_user }}"
password: "{{ tower_pass }}"
force_basic_auth: yes
status_code: 201
Same playbook using a token for registration:
--
- name: Tower API
hosts: localhost
gather_facts: false
vars:
tower_user: admin
tower_pass: myadminpassword
tower_host: 127.0.0.1
template_name: DEV template
tasks:
- name: Get the token
uri:
url: "https://{{ tower_host }}/api/v2/users/1/personal_tokens/"
method: POST
validate_certs: false
return_content: true
user: "{{ tower_user }}"
password: "{{ tower_pass }}"
force_basic_auth: true
status_code: 201
register: response
- name: Use the token
uri:
url: "https://{{ tower_host }}/api/v2/job_templates/{{ template_name | urlencode }}/launch/"
method: POST
validate_certs: false
return_content: true
status_code: 201
headers:
Authorization: "Bearer {{ response['json']['token'] }}"
Content-Type: "application/json"
register: launch
Conclusion
AWX REST API is well designed and let you do almost all operation from command line. It is easy to create scripts to manage these operations. In the next blog I will explain how to get out all logs between two dates from AWX, and put them on the disk for an easy troubleshooting.
Jeremy
17.09.2023Cool article but why are we using the GUI in order to use the API, that defeats the purpose in most use cases. And really your gunna make a playbook with some dynamic job number you got? Am I just confused?