This commit is contained in:
Gilles Mouchet 2025-05-30 08:11:49 +02:00
commit ad75f53a28
4 changed files with 336 additions and 0 deletions

5
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,5 @@
{
"editor.fontSize": 13,
"terminal.integrated.fontSize": 13,
"window.zoomLevel": 1.4,
}

34
LICENSE Normal file
View File

@ -0,0 +1,34 @@
Non-Commercial Use License [sync-awx-inventory.sh]
Copyright (c) [2025] [Gilles Mouchet]
This script is provided free of charge with its source code. You are permitted to:
Use the script for personal, educational, or non-commercial professional purposes.
Study, modify, and share the script freely, provided this license is included.
You are strictly prohibited from:
- Selling this script or any modified version.
- Using it in commercial services or products.
- Distributing it in exchange for financial compensation, directly or indirectly.
This script is provided "as is", without any warranty of any kind.
-----------------------------------------------------------------------------------------
Licence dutilisation non commerciale [sync-awx-inventory.sh]
Copyright (c) [2025] [Gilles Mouchet]
Ce script est fourni gratuitement avec son code source. Toute personne est autorisée à :
Utiliser le script à des fins personnelles, éducatives ou professionnelles non commerciales.
Étudier, modifier et partager le script gratuitement, à condition de conserver cette licence.
Il est strictement interdit de :
- Vendre ce script ou une version modifiée.
- Lutiliser dans des services ou produits commerciaux.
- Le distribuer en échange dune contrepartie financière, directe ou indirecte.
Ce script est fourni "tel quel", sans garantie daucune sorte.

40
README.md Normal file
View File

@ -0,0 +1,40 @@
# Sync-awx-inventory
## Description
This script this script synchronize the hosts source file with an AWX inventory
## Requirements
- [Rocky 9 GMo](https://gmodocs.dyndns.org/system/rocky/installation/)
- Package
- jq
## Installation
### Script
```bash
cp sync-awx-inventory /usr/local/bin/
```
### AWX credentials
Authentication by token. See [](https://ansible.readthedocs.io/projects/awx/en/latest/) to create token
```bash
cat << EOF > $HOME/.awxcred
token=werfgg....drf
```
### Cron
```bash
echo " */7 * * * * root ./usr/local/bin/sync-awx-inventory.sh > /dev/null 2>&1" > /etc/cron/sync-awx-inventory.cron
```
## Usage
```bash
sudo /usr/local/bin/sync-awx-inventory.sh --help
```
## Logs
```bash
sudo journalctl -f -t syn_awx_inv
```
## Changelog
#### [1.0] - 29.05.2025
##### Added
- Version from scratch by [GMo](mailto:gilles.mouchet@gmail.com)

257
sync-awx-inventory.sh Executable file
View File

@ -0,0 +1,257 @@
#!/bin/bash
############################################################
# Decription: this script synchronize the hosts source
# file with an AWX inventory
#
# Author: Gilles Mouchet (gilles.mouchet@gmail.com)
# Creation Date: 29.05.2025
# Version: 1.0
#
# Install: see README.md
# Usage: ./sync-awx-inventory.sh --help
# Changelog:
# V1.0 - 29.05.2025 - GMo
# Added
# - Creation of script from scratch
#
############################################################
version=1.0
#user=user_name
#pass=secret
cred_file=$HOME/.awxcred
# awx server
awx_srv=awx
awx_srv_url=https://${awx_srv}.gmolab.net
# awx inventory name
awx_inventory=linux
# search domain in hosts file
search_domain=gmolab
search_domain_prefix=net
# hosts file
src_hosts_file=/etc/hosts
log_tag=syn_awx_inv
# array of host name in /etc/hosts
hosts_array=()
#----- FUNCTIONS -----#
# function add host in awx inventory
add_host_in_awx() { #inventories/{id}/hosts/
api_rc=$(curl -s -o /dev/null -w "%{http_code}" -X POST "$awx_srv_url/api/v2/hosts/" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $awx_token" \
-d @- <<EOF
{
"name": "$1",
"inventory": $inventory_id
}
EOF
)
#echo $api_rc
return $api_rc
}
# function delete host from AWX inventory
del_host_from_awx() {
# get host id
host_id=$(curl -s -H "Authorization: Bearer $awx_token" \
"$awx_srv_url/api/v2/inventories/$inventory_id/hosts/?name=$1" | jq -r '.results[0].id')
# check if host exist in inventory
if [[ "$host_id" == "null" || -z "$host_id" ]]; then
msg="'$1' not found in inventory id."
echo ${msg}; logger -t $log_tag ${msg}
exit 1
fi
# delete host
api_rc=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE \
-H "Authorization: Bearer $awx_token" \
"$awx_srv_url/api/v2/hosts/$host_id/")
return $api_rc
}
#--------------------------#
# END FUNCTION #
#--------------------------#
#--------------------------#
# MAIN #
#--------------------------#
# display stdout and stderr on screen and on log
# to read log use sudo "journalctl -f -t syn_awx_inv" command
exec > >(tee /dev/tty | logger -t $log_tag)
exec 2> >(tee /dev/tty >&2 | logger -t $log_tag)
case $1 in
-p|--parameter)
cat << EOF
Credentials file (\$cred_file): $cred_file
Source file (\$src_hosts_file): $src_hosts_file
AWX inventory (\$awx_inventory): $awx_inventory
Domain search in src (\$search_domain): $search_domain.$search_domain_prefix
AWX server url (\$awx_srv_url): $awx_srv_url
Log tag (\$log_tag): $log_tag
EOF
exit 1
;;
-h|--help)
cat << EOF
Usage: $(basename "$0") OPTIONS
Synchronizes the hosts source file with an AWX inventory
Options:
-p, --parameter display parameters
-l, --help display this help text and exit
-v, --version display the verion
EOF
exit
;;
-v|--version)
cat << EOF
$(basename "$0") v$version (c) 1990 - $(date +%Y) by Gilles Mouchet
Non-Commercial Use License See LICENSE for details
EOF
exit
;;
esac
logger -t $log_tag "[INFO] - start script"
#check if awx server is up
if ! nc -z -w 2 $awx_srv 22 2>/dev/null; then
echo "[ERROR] - server '$awx_srv_url' is not up"
exit 1
fi
# read awx credential
if [ -f $cred_file ]; then
awx_token=$(grep "token=" $cred_file | cut -d'=' -f2)
else
echo "[ERROR] - file $cred_file not found !"
exit 1
fi
#---------- create host list from inventory
# get inventory id
inventory_id=$(curl -s -H "Authorization: Bearer $awx_token" \
"$awx_srv_url/api/v2/inventories/?name=$awx_inventory"| jq -r '.results[0].id')
# get inventory items
# this curl display onliy the 25 first host (pagination)
#awx_item=$(curl -s -H "Authorization: Bearer $awx_token" \
# "$awx_srv_url/api/v2/inventories/$inventory_id/hosts/")
# this get ALL hosts in inventory
next_url="$awx_srv_url/api/v2/inventories/$inventory_id/hosts/"
while [ -n "$next_url" ] && [ "$next_url" != "null" ]; do
awx_item=$(curl -s -H "Authorization: Bearer $awx_token" -H "Accept: application/json" "$next_url")
# extract hostnames and add them to the table
mapfile -t new_hosts < <(echo "$awx_item" | jq -r '.results[].name')
hosts_in_awx+=("${new_hosts[@]}")
next_url=$(echo "$awx_item" | jq -r '.next')
# complete the URL if necessary
if [[ "$next_url" =~ ^/ ]]; then
next_url="$awx_srv_url$next_url"
fi
done
#---------- create host list from hosts file
# read hosts fiée
while IFS= read -r line; do
hosts_in_file+=("$line")
done < <( grep -v '^#' $src_hosts_file \
| sed 's/#.*//' \
| tr -s ' ' \
| tr '\t' ' ' \
| cut -d ' ' -f2- \
| tr ' ' '\n' \
| grep '\.'$search_domain'\.'$search_domain_prefix'$' \
| sed 's/\.'$search_domain'\.'$search_domain_prefix'$//' \
| sort -u
)
#
# for debug only
# test for pagination 30 hosts
#hosts_in_file=(titi gros-minet tom jerry cortex minus road-runner coyote bugs-bunny riri fifi loulou picsou \
# donald-duck mickey pluto mister-magoo droopy calimero scooby-doo samy daffy-duck popey \
# woody-woodpecker garfield casper winnie casper homer marge bart)
# test for pagination 25 hosts
#hosts_in_file=(titi gros-minet tom jerry cortex minus road-runner coyote bugs-bunny fifi loulou picsou \
# donald-duck mickey scooby-doo samy daffy-duck popey \
# woody-woodpecker garfield casper winnie casper homer marge bart)
# CAUTION delete all host in AWX inventory
#hosts_in_file=()
#---------- add host in awx inventory if not exixts
echo "[INFO] - add host to '$awx_inventory' AWX inventory"
action_add=false
# loop on each element of the source host file
for item_host in "${hosts_in_file[@]}"; do
found=false
# loop on each item from awx inventory
for item_awx in "${hosts_in_awx[@]}"; do
# check if host in source exist in awx inventoy
if [[ "$item_host" == "$item_awx" ]]; then
found=true
break
fi
done
# if not found, add host into awx inventory
if ! $found; then
action_add=true
add_host_in_awx $item_host
rc=$?
if [ "$rc" -eq "201" ]; then
echo "[SUCCESS] - host '$item_host' successfully added to '$awx_inventory' AWX inventory"
else
echo "[ERROR] - error $rc when adding '$item_host' to '$awx_inventory' AWX inventory"
#exit 1
fi
fi
done
if ! $action_add; then
echo "[INFO] - no hosts added to AWX '$awx_inventory' inventory"
fi
echo ""
#---------- check if hosts from awx exist in the source host file
#---------- if not, delete from awx inventory
echo "[INFO] - delete host from '$awx_inventory' AWX inventory"
action_del=false
# loop on each item from awx inventory
for item_awx in "${hosts_in_awx[@]}"; do
found=false
# loop on each element of the source host file
for item_host in "${hosts_in_file[@]}"; do
# check if host in awx inventory exist in the source host file
if [[ "$item_awx" == "$item_host" ]]; then
found=true
break
fi
done
# if not found, delete host from awx inventory
if ! $found; then
action_del=true
del_host_from_awx $item_awx
rc=$?
if [[ "$rc" == "204" ]]; then
echo "[SUCCESS] - host '$item_awx' successfully deleted from '$awx_inventory' inventory"
else
echo "[ERROR] - error $rc when deleting '$item_awx' from '$awx_inventory' AWX inventory"
exit 1
fi
fi
done
if ! $action_del; then
echo "[INFO] - no host to delete from '$awx_inventory AWX inventory"
fi
echo ""
echo "[INFO] - the '$awx_inventory' inventory on AWX is up to date"
logger -t $log_tag "[INFO] - start script"