Ansible AWX Guide: from scratch to REST API (4/8)
Presents two Ansible playbooks that automate AWX REST API calls to disable or remove hosts from an inventory.
What this file does
Presents two Ansible playbooks that automate AWX REST API calls to disable or remove hosts from an inventory.
When to use it
- You need to manage AWX inventory hosts via playbook instead of scripts
- You want to see how the uri module can replace Ansible Tower modules for API interactions
- You are following a multi-part guide on AWX REST API automation
Assumes this stack
Ansible AWX Guide: from scratch to REST API (4/8)
Playbook to automate AWX REST API interactions
This topic is a review of two ansible playbooks.
REST API interactions shown in the previous topic have been converted to playbook, which will be used by Workflow later.
In real envinroment that uses Ansible for configuration management, playbooks are always preferred instead scripts.
Table of Contents
- Concepts
- Playbook directory structure
- The awx-api-inventory playbook
- The basic playbook
- Summary
- References
Concepts
What is Ansible Playbook
Playbooks are Ansible’s configuration, deployment, and orchestration language. They can describe a policy you want your remote systems to enforce, or a set of steps in a general IT process. <sup>1</sup>
Playbook directory structure
Two playbooks has been developed for this guide, see README.md for more details at: https://github.com/cdomingos/ansible-playbook-awxapiinventory.git

The awx-api-inventory playbook
A playbook which interacts with REST API that is able to remove or disable host in inventory.
This playbook uses uri ansible module.
---
- name: MANAGE HOST IN AWX/TOWER INVENTORY USING REST API
hosts: all
connection: local
gather_facts: false
vars:
api_awx_inventory: "{{ awx_inventory_name | default(tower_inventory_name, True) }}"
tasks:
- name: Check REST API credentials
uri:
url: "{{ api_awx_url | regex_replace('(/+)$') }}/api/v2/me/"
method: GET
validate_certs: false
user: "{{ api_awx_username }}"
password: "{{ api_awx_password }}"
return_content: true
force_basic_auth: true
status_code: 200
- name: Get inventory id
uri:
url: "{{ api_awx_url | regex_replace('(/+)$') }}/api/v2/inventories/?name={{ api_awx_inventory | urlencode }}"
method: GET
validate_certs: false
user: "{{ api_awx_username }}"
password: "{{ api_awx_password }}"
return_content: true
force_basic_auth: true
status_code: 200
register: reg_uri_get_inventory_id
failed_when: reg_uri_get_inventory_id.json.count == 0
- name: Set fact_inventory_id
set_fact:
fact_inventory_id: "{{ item.id | int }}"
loop: "{{ reg_uri_get_inventory_id.json.results }}"
loop_control:
label: "{{ item.id | int }}"
when:
- item.name == api_awx_inventory
- name: Check if fact_inventory_id is valid
assert:
that:
- fact_inventory_id is defined
- fact_inventory_id | length > 0
- name: Check if managed node exists in inventory
uri:
url: "{{ api_awx_url | regex_replace('(/+)$') }}/api/v2/inventories/{{ fact_inventory_id }}/hosts/?name={{ inventory_hostname }}"
method: GET
validate_certs: false
user: "{{ api_awx_username }}"
password: "{{ api_awx_password }}"
return_content: false
force_basic_auth: true
register: reg_uri_host_check
- when: reg_uri_host_check.json.count > 0
block:
# the loop maybe run without arguments when entire block is skipped,
# this is an elegant way to avoid this behavior
- name: Set fact_host_id
set_fact:
fact_host_id: "{{ item.id | int }}"
loop: "{{ host_id_loopvar }}"
loop_control:
label: "{{ item.id | default('skip', True) }}"
when:
- item.name == inventory_hostname
vars:
host_id_loopvar: "{{ reg_uri_host_check.json.results | default(['skip'], True) }}"
- name: Check if fact_host_id is valid
assert:
that:
- fact_host_id is defined
- fact_host_id | length > 0
- fact_host_id != "skip"
- name: Check if managed node id exists
uri:
url: "{{ api_awx_url | regex_replace('(/+)$') }}/api/v2/hosts/{{ fact_host_id | int }}/"
method: GET
validate_certs: false
user: "{{ api_awx_username }}"
password: "{{ api_awx_password }}"
return_content: true
force_basic_auth: true
status_code: 200
- name: Disable managed node in inventory
uri:
url: "{{ api_awx_url | regex_replace('(/+)$') }}/api/v2/hosts/{{ fact_host_id | int }}/"
method: PATCH
validate_certs: false
user: "{{ api_awx_username }}"
password: "{{ api_awx_password }}"
return_content: false
force_basic_auth: true
status_code: 200
body:
enabled: false
body_format: json
changed_when: true
when:
- api_inventory_disable is defined
- api_inventory_disable | bool
- name: Disassociate managed node from inventory
uri:
url: "{{ api_awx_url | regex_replace('(/+)$') }}/api/v2/inventories/{{ fact_inventory_id }}/hosts/"
method: POST
validate_certs: false
user: "{{ api_awx_username }}"
password: "{{ api_awx_password }}"
return_content: true
force_basic_auth: true
status_code: 204
body: "{'id': {{ fact_host_id | int }}, 'disassociate': true }"
body_format: json
register: reg_uri_host_disassociate
changed_when: true
when:
- api_inventory_remove is defined
- api_inventory_remove | bool
- name: Check if managed host still exists in inventory
uri:
url: "{{ api_awx_url | regex_replace('(/+)$') }}/api/v2/inventories/{{ fact_inventory_id }}/hosts/{{ fact_host_id | int }}/"
method: GET
validate_certs: false
user: "{{ api_awx_username }}"
password: "{{ api_awx_password }}"
return_content: false
force_basic_auth: true
register: reg_uri_host_checkagain
failed_when: reg_uri_host_checkagain.status == 200
when:
- api_inventory_remove is defined
- api_inventory_remove | bool
This playbook could be rewritten using Ansible_Tower modules, but I choose the uri module to expand API usage.
The basic playbook
A basic playbook which do simple tasks.
---
- name: BASIC TASKS
hosts: all
gather_facts: false
tasks:
- name: Ensure ansible user exists
user:
name: ansible
state: present
- name: Test host connectivity
ping:
Summary
In this topic was presented:
- Review an example playbook to automate API interactions using uri ansible module.
References
[1] - https://docs.ansible.com/ansible/latest/user_guide/playbooks.html
Continue Reading
Next topic: Creating a remote user for Ansible
What's inside
2 playbooks, 1 with 11 tasks for inventory management, 1 with 2 basic tasks
Change this for your project
- Replace
api_awx_urlwith your AWX server URL - Replace
api_awx_usernameandapi_awx_passwordwith your credentials - Replace
api_awx_inventorywith your target inventory name
Where it goes
Keep it in your repository where the agent or team that needs it will read it.
Worth borrowing
- Using the uri module to authenticate and perform CRUD operations against AWX API
- Conditional block execution with
whenandblockto handle host existence checks
Related Documents
Video/Content Producer
Defines a video/content producer role with script structures, hook formulas, storyboard templates, and platform-specific formats for short-form and long-form video production.
Media Handling Playbook - Zyeuté v3
Documents upload, storage, optimization, delivery, and edge-case handling for images, videos, and audio in a social app.
Visual Truth Engine: Product-Market Fit & Go-to-Market Strategy
Outlines a product-market fit strategy and go-to-market plan for a B2B SaaS tool that automates proof asset creation for video creators.
Devin Triage Playbook
Defines a 7-phase automated triage playbook for Devin to analyze alerts, find root causes, implement fixes, and notify teams.