Ansible inventory script - inventaire dynamique 1

Voir :

https://goetzrieger.github.io/ansible-tower-advanced/9-advanced-inventories/

Voir aussi :

https://www.redhat.com/sysadmin/ansible-plugin-inventory-files

https://github.com/ansible-community/contrib-scripts/blob/main/inventory/ssh_config.py

Nous allons coder un inventory script en bash en mode “hello world”

Voici le script bash avec des données codés en dures dedans, c'est moche mais c'est juste pour un PoC.

#! /bin/bash set -euo pipefail IFS=$' \t\n' export LANG=C SCRIPT_NAME="$(basename "$0")" trap 'rm -f "$TMP_INV_INI"' EXIT TMP_INV_INI="$(mktemp --suffix=_"${SCRIPT_NAME%%.*}".ini)" mk_ini_tmp_inv() { cat <<-EOF >"$TMP_INV_INI" [all:vars] os = linux [web] srv-web1 web=1 srv-web2 web=2 [db] srv-db1 db=1 srv-db2 db=2 [plop] test-ansible EOF } arg_list() { mk_ini_tmp_inv ansible-inventory -i "$TMP_INV_INI" --list } arg_host() { mk_ini_tmp_inv ansible-inventory -i "$TMP_INV_INI" --host "$1" } usage() { ansible-doc -t inventory script } while [ "${1-}" != "" ]; do case $1 in --list ) shift arg_list ;; --host ) shift arg_host "$1" ;; -h | --help ) usage exit 0 ;; --) # End of all options shift break ;; -*) echo "SCRIPT_NAME: invalid option" >&2 echo "Try '$SCRIPT_NAME --help' for more information." >&2 exit 1 ;; *) usage ;; esac shift done

Rendons le script exécutable

chmod +x inv.sh

Nous testons la sortie de notre script bash

./inv.sh --list
{ "_meta": { "hostvars": { "srv-db1": { "db": 1, "os": "linux" }, "srv-db2": { "db": 2, "os": "linux" }, "srv-web1": { "os": "linux", "web": 1 }, "srv-web2": { "os": "linux", "web": 2 }, "test-ansible": { "os": "linux" } } }, "all": { "children": [ "db", "plop", "ungrouped", "web" ] }, "db": { "hosts": [ "srv-db1", "srv-db2" ] }, "plop": { "hosts": [ "test-ansible" ] }, "web": { "hosts": [ "srv-web1", "srv-web2" ] } }

Nous testons de nouveau la sortie de notre script mais pour un host spécifique cette fois

./inv.sh --host srv-web1
{ "os": "linux", "web": 1 }

A présent testons avec Ansible :

$ ansible -i inv.sh -m ping plop
[WARNING]: * Failed to parse /home/jean/tmp/inv.sh with script plugin: Inventory script (/home/jean/tmp/inv.sh) had an execution error:
[WARNING]: * Failed to parse /home/jean/tmp/inv.sh with ini plugin: /home/jean/tmp/inv.sh:3: Expected key=value host variable assignment, got: -euo
[WARNING]: Unable to parse /home/jean/tmp/inv.sh as an inventory source
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
[WARNING]: Could not match supplied host pattern, ignoring: plop

Ça ne marche pas. Ansible s'attend à trouver un inventaire au format ini et à la place il a du bash.

Les inventory script doivent être en Python. J'ai essayé de renommer ce script inv.sh en inv.py mais ça ne marche pas.

Nous allons coder un wrapper Python qui lance notre script bash.

#! /usr/bin/env python3 import os import argparse parser = argparse.ArgumentParser() parser.add_argument('--list', action='store_true') parser.add_argument('--host') args = parser.parse_args() if args.list: os.system('bash ./inv.sh --list') elif args.host: os.system(f'bash ./inv.sh --host {args.host}')

Rendons ce script Python exécutable

chmod +x inv.py

Et ça marche :

$ ansible -i inv.py -m ping plop
test-ansible | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}

Autres

Voir

Enabled Variable

Retrieve the enabled state from the given dict of host variables. The enabled variable may be specified using dot notation, e.g: 'foo.bar'