На чем было опробовано:
- Ansible 2.9.18
- Hyper-V на Windows 10 Pro.
- Сервер Ansible: CentOS Linux release 7.9.2009 (Core).
- Node 1: CentOS Linux release 7.9.2009 (Core).
- Node 2: CentOS Linux release 7.9.2009 (Core).
- Node 3: CentOS Linux release 7.9.2009 (Core).
- Node 4: CentOS Linux release 7.9.2009 (Core).
1. Задача.
Собранная информация должна формироваться в json-формат.
2. Решение задачи.
Решение будет состоять из нескольких этапов:
- загрузка и выполнение скрипта на узлах с целью получить json файлы;
- выгрузка файлов json с узлов;
- склеивание узловых файлов json в один сводный файл;
- просмотр сводного файла.
Для этого существует возможность добавления Custom facts, что делается следующим образом:
- на любом хосте, контролируемом Ansible, создаётся каталог
/etc/ansible/facts.d
; - внутри каталога размещаются один либо несколько файлов с расширением
*.fact
, напримерcustom.fact
; - файлы возвращают данные в формате json.
Создаем инвентарь test-servers.inventory
на 4 тестовых сервера:
# mcedit /ansible/test-servers.inventory
[test_servers]
server1 ansible_ssh_host=192.168.0.39 ansible_ssh_user=root
server2 ansible_ssh_host=192.168.0.30 ansible_ssh_user=root
server3 ansible_ssh_host=192.168.0.31 ansible_ssh_user=root
emachines ansible_ssh_host=192.168.0.12 ansible_ssh_user=root
По замыслу будут собираться некоторые переменные и заворачиваться в разметку json.
#!/bin/bash
file_po="/etc/po/version.txt"
host_name=$(hostname)
ecp_ver=$(awk -F: '/rel_ver/{print $2}' $file_po)
docker_info=$(docker ps --format ' {{json .Names}}: {{json .Image}}, ' | paste -sd'n' | sed '$ s/.$//')
jp="/$host_name.json"
echo "{" > $jp
echo ""Информация об узлах": {" >> $jp
echo ""$host_name": {" >> $jp
if test -f "$file_po"; then
echo ""Софт": {" >> $jp
echo ""Версия чего-то": "$ecp_ver"" >> $jp
echo "}" >> $jp
echo "," >> $jp
fi
echo ""Докеры на узле": {" >> $jp
echo "$docker_info" >> $jp
echo "}" >> $jp
echo "}" >> $jp
echo "}" >> $jp
echo "}" >> $jp
---
- name: "Cбор Ansible custom facts"
hosts: all
tasks:
- name: "Удаление предыдущей версии Ansible custom facts файлов на узле"
file:
state: "absent"
path: "/etc/ansible/facts.d/"
- name: "Создание Ansible custom fact каталога"
file:
path: "/etc/ansible/facts.d"
state: "directory"
mode: 0766
- name: "Загрузка на узлы Ansible custom fact файлов"
copy:
src: "/ansible/files/custom.fact"
dest: "/etc/ansible/facts.d/custom.fact"
mode: +x
- name: "Объявление служебной переменной для Ansible custom fact"
debug: "var=ansible_local"
notify:
- reload facts
- name: "Перезагрузка facts"
setup: "filter=ansible_local"
- name: "Подготовка списка файлов *.json для выгрузки с узла"
find:
paths: "/"
recurse: "no"
patterns: "*.json"
register: "files_to_copy"
- name: "Выгрузка файлов *.json с узла на Ansible master сервер"
fetch:
src: "{{ item.path }}"
dest: "/ansible/json"
with_items: "{{ files_to_copy.files }}"
Напишем скрипт custom-facts-fetch-PLAY.sh
для запуска playbook на целевом inventory:
#!/bin/bash.
ansible-playbook /ansible/custom-facts-fetch.yml -i /ansible/test-servers.inventory
Сделаем файл скрипта исполняемым:
# chmod +x custom-facts-fetch-PLAY.sh


В каждом из которых будет находиться json файл вида имя_узла.json
:




Содержимое json файла первого узла emachines
:

Содержимое json файла второго узла server1
:

Содержимое json файла третьего узла server2
:

Содержимое json файла четвертого узла server3
:

Получилось несколько файлов json, по файлу с каждого целевого узла.
Сколько узлов мы задействовали для Ansible custom facts, столько и json файлов и будет.
Для создание сводного json файла по всем файлам со всех узлам, воспользуемся утилитой jq.
Ссылка на официальный сайт утилиты: https://stedolan.github.io/jq/.
Установка утилиты:
# yum install jq -y
План работ с файлами:
file1.json + file3.json + file3.json + file4.json = final_result_po.json
Создадим make-final-json-file.sh
скрипт:
# mcedit /ansible/make-final-json-file.sh
#!/bin/bash
#создание каталогов для обработки файлов
mkdir -p /ansible/json/temp
mkdir -p /ansible/json-ready
#каталог куда Ansible кладет скачанные json файлы с узлов
ja="/ansible/json"
#временный каталог куда Ansible складывает все json файлы из всех каталогов узлов перед сведением информации в единый файл json
jrt="/ansible/json/temp"
#каталог куда Ansible помещает сводный json файл со всей добытой информацией по узлам
jr="/ansible/json-ready"
#обработка файлов и удаление временных промежуточных результатов
cp -i $(find /$ja -iname "*.json") $jrt
cd $jrt
jq -s '.[0] * .[1] * .[2] * .[3]' *.json > "$jrt"/temp.json
cat "$jrt"/temp.json | sed 's/{}/"нет докеров"/' > "$jr"/final_result_po.json
#удаление временных каталогов и файлов
rm -rf $jrt
rm -rf $ja
Сделаем файл скрипта исполняемым:
# chmod +x /ansible/make-final-json-file.sh
Результатом работы скрипта будет сводный json файл всех четырёх final_result_po.json
в каталоге /ansible/json_ready
на Ansible master сервере:

Текстовый файл:
{
"Информация об узлах": {
"cos7client1.hamsterden.loc": {
"Софт": {
"Версия чего-то": "9.11.2"
},
"Докеры на узле": {
"wordpress-compose_nginx_1": "nginx:latest",
"wordpress-compose_wordpress_1": "wordpress:php7.4-fpm-alpine",
"wordpress-compose_pma_1": "phpmyadmin/phpmyadmin",
"wordpress-compose_mysql_1": "mariadb"
}
},
"cos7client2.hamsterden.loc": {
"Софт": {
"Версия чего-то": "10.2.1"
},
"Докеры на узле": "нет докеров"
},
"cos7client3.hamsterden.loc": {
"Софт": {
"Версия чего-то": "9.3.4"
},
"Докеры на узле": "нет докеров"
},
"emachines.hamsterden.loc": {
"Докеры на узле": {
"onlyoffice": "onlyoffice/documentserver",
"funny_heisenberg": "onlyoffice/documentserver"
}
}
}
}
Если открыть final_result_po.json
файл в браузере Mozilla Firefox, то информация будет корректно визуализирована в удобно читаемом виде:

Задача выполнена!
X. Оригиналы источников информации.
- golinuxcloud.com «Working with Ansible facts | Create custom facts with examples».
- github.com «Ansible local fact example».
- medium.com «Custom facts for Ansible».
- otus.ru «Ansible: формируем переменные на всех хостах с Custom facts».
- mydailytutorials.com «Working with Ansible facts – retrieving facts».
- adyxax.org «Ansible custom factsAnsible custom facts».
- Источник: https://hamsterden.ru/ansible-collecting-arbitrary-information-on-all-hosts-with-custom-facts/