Ansible APIs¶
In Ansible AWX, everything (even the UI), is driven from the API, which extensively leverages Django DRF.
Warning
This requires the following dependencies and has been tested at these specified versions:
Explore Django DRF API¶
The primary URL for accessing Ansible AWX's Django DRF API is usually https://<awx_server>/api/v2/. Ensure you have the appropriate permissions and that the API endpoint is accessible.
Objects in AWX are based on Django DRF, which help you traverse the parent-child relationships of the database. For instance, a job template might be tied to a specific inventory or project. This hierarchical nature means certain API calls might depend on IDs or details retrieved from a different endpoint.
All of the endpoints can be navigated from here, a few highlights would be:
- Jobs: (
https://<awx_server>/api/v2/jobs/) Retrieve information about job runs, their status, and results. - Job Templates: (
https://<awx_server>/api/v2/job_templates/) Understand the predefined tasks and their configurations. - Inventories: (
https://<awx_server>/api/v2/inventories/) Get information about hosts, groups, and associated variables.
Warning
Make sure to always include a trailing slash on the api call.
Info
In the DRF interface, you can click generally click on links to navigate directly to related resources.
You can run API calls right from the UI. When there is an applicable update, you can make it via the bottom hand page.
Explore Django DRF API - LAB¶
- Review the Django DRF interface, especially jobs, job_templates, and inventories.
- Make a
PATCHcall on one of the inventories, make sure to remove all variables you do not want to touch.
Access Tokens¶
The API is accessible via multiple credentials methods, for the purpose of this lab, we will use a token, but you could also use user/password credentials.
Access Tokens - LAB¶
To obtain a token from the UI, follow these steps:
- In the top right, navigate to
{{ your_username}} -> User Details - Navigate to the
Tokenstab, clickAdd - Fill out with:
- Description:
{{ initials }} Token - Scope: write
- Description:
- Click
Save - Make sure to copy your token!!!
- Test your token with
curl -k -X GET -H "Authorization: Bearer YOUR_TOKEN" https://<awx_server>/api/v2/ping/
Curl API calls¶
While Curl (or Postman) does not provide great mechanisms for interacting (e.g. making a call, gathering data, making another call from that data) with APIs, they do provide a great test place to understand basic API calls.
Let's explore a few different API calls.
Find the ID via Django DRF or you can see it in the UI is the URL of a given job template.
# Using Job ID
curl -X POST -H "Authorization: Bearer YOUR_TOKEN" https://<awx_server>/api/v2/job_templates/{90}/launch/
# Using Job Name
curl -X POST -H "Authorization: Bearer YOUR_TOKEN" https://<awx_server>/api/v2/job_templates/{job-name}/launch/
Curl API calls - LAB¶
Run through the provided Curl commands.
Python Requests API Calls¶
For any series of API calls, Curl (or Postman) can provide some quick and dirty help. However, that logic to find IDs dynamically or deal with an asynchronous API is rather difficult without a programming language. We will review how to use Python requests to work with Ansible AWX APIs.
Warning
An asynchronous API will immediately return a return code indicting that the message has been successfully received, but it does not let you know when the job is complete. You have to make an API call to another endpoint to indicate the completion of the job, **luckily, the AWX API provides you with that URL in the return code"
import requests
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
AWX_URL = "awx.ntcu.ntc.dev/"
JOB_TEMPLATE_ID = 'nautobot-environment'
TOKEN = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" # replace with your actual token
# Set the headers for authentication and content type
headers = {
"Authorization": f"Bearer {TOKEN}",
"Content-Type": "application/json"
}
response = requests.get(f'https://{AWX_URL}/api/v2/inventories/', headers=headers)
if response.status_code == 200:
print(response.json())
else:
print(f"Error: {response.status_code}")
The Ansible AWX API allows for various parameters when launching a job via the /api/v2/job_templates/{id}/launch/ endpoint. When we talk about launching a job from a Job Template, several key parameters come into play.
limit: Refers to the host limit, where you can specify a subset of hosts from the inventory to run the job against. It accepts a pattern or a comma-separated list ofhosts, as you would find in an Ansible Playbook.extra_vars: Variables that you pass to the playbook at runtime. These are in JSON format when passed via the API. For instance:{"key1": "value1", "key2": "value2"}.job_tags: This allows you to run only specific parts of the playbook by specifying tags.skip_tags: Skips tasks associated with specified tags.job_type: Determines how the job will run. It can be 'run' (default) or 'check'. The 'check' mode performs a dry run.inventory: ID of the inventory you want to use. By default, it would use the inventory associated with the job template.credentials: List of credential IDs to use for the job. This might override the default credentials set in the job template.
There are other parameters as well, like diff_mode, verbosity, etc., but the ones listed above are some of the more commonly used ones.
When you configure a Job Template in Ansible AWX, you can set various fields to "Prompt on Launch". This means that when a user initiates a job run from this template (whether from the UI or the API), they will be prompted to provide values for these fields.
- If you've set a field (like
limitorextra_vars) to "Prompt on Launch" in the UI, and then you use the API to launch the job without providing that parameter, AWX will expect that piece of data to be provided elsewhere, or it might use the default specified in the job template. - If you do provide the parameter in the API call, it will override whatever default is specified in the job template for that run.
- If a parameter is set to "Prompt on Launch" but is not provided in the API call and doesn't have a default in the job template, the job launch might fail.
In summary, the "Prompt on Launch" option in the UI gives flexibility when launching jobs but also "enables" that feature via the API.
data = {
"extra_vars": {"key1": "value1", "key2": "value2"}
}
job_name = "hello-world" # or alternate name
response = requests.post(f'https://{AWX_URL}/api/v2/job_templates/{job_name}/launch/', headers=headers, json=data)
if response.status_code == 201:
print("Job successfully created!")
print(response.json())
else:
print(f"Error: {response.status_code}")
Python Requests API Calls - LAB¶
- Run through the two provided examples
- Toggle the options (extra_vars, limit, etc)
- Build a process to run the job, and wait for the job to be complete.
- Hint: Use the data returned in the job_template launch to find next API call
- Hint: A while loop would likely be best in this situation.