9

Ansible для детского сада. Часть 5. Приделываем костыли

Серия Кудахтеры: Ansible

У меня постоянное ощущение того, что я описываю не велосипед с костылями, а велосипед, который давно изобретен, на котором все катались лет 15 назад, если не 20. Что-то типа «введение в линукс и все вокруг для 10 класса». Что на информатике учат.

Для лиги лени: много примеров, как делать не надо, и как точно не работает

Ansible для детского сада в скольки то частях. Часть 1.Про все сразу
Ansible для детского сада в скольки то частях. Часть 2. Костылируем жалкое подобие WSUS - Linux Server Update Services (LSUS)
Ansible для детского сада. Часть 3. Настраиваем подобие безопасности и все остальное
Подготовка Git

Ansible для детского сада. Часть 4. Первичная настройка конечного клиента
4.1 Теоретически все просто
4.2 Сначала готовим открытую часть сертификата без пароля через Putty в Windows и еще раз вспоминаем что генерирует Putty в Windows, а что нужно в ssh
4.3 Детский скрипт, и как не надо делать
4.4 Отлаживаем SSH, снова и опять
4.5 Проблемы с переносом строки и не только
4.6 Проверяем, что получилось
4.7 Почти переходим к второму Ansible плейбуку
4.8 Воюем с пробелами в Anisble и восстанавливаем пример из первой статьи
4.9 Возвращаемся к основной задаче

Ansible для детского сада в скольки то частях. Часть 5. Приделываем костыли
5.1 Теоретическое обоснование костылей, или «зачем».
5.2 Выбор dataflow
5.3 Собираем Ansible facts без плейбука
5.4 Разбираем полученную выгрузку

Ansible для детского сада в скольки то частях. Часть 5. Приделываем костыли

5.1 Теоретическое обоснование костылей, или «зачем».

С какого-то возраста появился вопрос: «Зачем?» Вот раньше тебе звонил приятель, например, говорил: «Слушай, я познакомился с двумя девушками, у них отдельная квартира в Отрадном, я выпить купил. Поехали!» И ты сразу ехал. Если бы тебя спросили: «А зачем?», ты бы сказал: «Ну как, зачем? Ты че, дурак? Две девушки, отдельная квартира! Посидим, выпьем, ну...» А сейчас...

Перед тем, как идти дальше, необходимо принять решение про архитектуру Linux Server Update Services (LSUS) на первом этапе. Поскольку сейчас я хочу только собирать и показывать статистику в нужном мне виде, с нужной детализацией. Часть информации я могу получать, не изобретая новую систему учета, а взяв имеющуюся, и переформатировав отчет из нее. Но насколько это будет сложно и долго? Нужен ли мне будет настоящий разработчик для такой задачи, потому что разработчик сделает ее быстрее, но сделает ли так, как мне надо? Учитывая, что я сам не знаю, как мне надо, значит, остается только попробовать сделать.

5.2 Выбор dataflow
Про что это? В результате обработки (входных данных) я получу (обработанные входные данные). Затем мне надо понять:
Где я буду обрабатывать сырые данные, на хосте с ansible или сделаю файл «как есть», положу его в общую папку (или как-то еще ?), заберу с хоста с Windows и там обработаю. Мне все равно, под что писать простой обработчик, под Windows или под Linux, и на чем писать – могу на баш (много секса, мало смысла), могу на питоне, могу на powershell. При малых объемах нет принципиальной разницы, обработается ли файл на 100 – 1.000 – 10.000 хостов за минуту, или за две.
Куда я помещу обработанные входные данные, в csv, xlsx, xml, или в web\html.
Если в web, то на каком веб-сервере? Апач, нжинкс, IIS, или даже MiniWeb и Small HTTP Server.
Нужно ли хранить исторические данные ?

Все это, и даже больше, я писал во второй части –

С целевой структурой данных ситуация сложнее. Для своего предпоследнего пет проекта под похожие задачи я просто развернул базу данных (Postgre), и туда клал разное. Нужно ли на первом шаге такое решение? Не знаю, мне не нужно, мне и бинарной таблицы хватит. Но что туда класть? Очевидно, туда должны попасть: FQDN, IP, дистрибутив, версия дистрибутива, ядро сейчас, последние дата и время доступности, аптайм. Должно ли туда попадать предыдущее состояние объекта, и какие-то еще настройки? Не очень важно, всегда можно расширить схему данных, добавить к объекту еще пару свойств.

Пока получается так, что сначала надо разобрать входной объект (файл, выгрузку), собрать из него данные в удобный мне массив объектов (или в список объектов, но это вопрос выбора алгоритма и понимания разницы работы с массивом и работы со списком). Когда будет массив данных в нужном мне виде, из него можно собрать уже то, что нужно мне.

5.3 Собираем Ansible facts без плейбука

Во второй части факты собирались одной командой,
ansible proxmox -m setup -a "filter=ansible_uptime_seconds" --ask-pass
В предыдущей (4-й) части я остановился на выполнении плейбука

ansible-playbook report23.yml --inventory  /home/user/second_inventory.ini --private-key  /home/ansible1/.ssh/ansible_key

Нужно ли делать плейбук именно для сбора фактов? Получается, что нет. Достаточно еще раз прочитать про ключи к ansible, и сделать:
[-i INVENTORY] [--list-hosts] [-l SUBSET] [--flush-cache]
[--private-key PRIVATE_KEY_FILE] [-u REMOTE_USER]

То есть выполнить все в одну команду:

ansible all --module-name setup --inventory  /home/user/second_inventory.ini --private-key  /home/ansible1/.ssh/ansible_key

не забывайте про all, даже если указываете --inventory  /home/user/second_inventory.ini.

на выводе вы получите текст ужасающей длины, в формате с {}, [], и еще чем-то. 150 килобайт на мои 3 (три) тестовые виртуальные машины.

Из этого огромного массива представляет интерес:

FQDN, IP, дистрибутив, версия дистрибутива, ядро сейчас, последние дата и время доступности, аптайм. То есть, в нужный мне объект должны попасть:
Удачность соединения: 192.168.1111.2222 | SUCCESS => {
FQDN: "ansible_fqdn"
Hostname: "ansible_hostname"
IP: "ansible_all_ipv4_addresses"
IPv6: "ansible_all_ipv6_addresses":
тип: "ansible_board_name": "Virtual Machine",
Текущие сессии: "SSH_CONNECTION":
Текущий пользователь "USER": "ansible1",. С этим параметром надо поработать, а то есть любители забыть закрыть сессию.
MAC "macaddress": ". Нужен, но не для сетевых настроек, а для сверки, не сделал ли кто-то, случайно, клонирование с совпадающим MAC адресом. Бывает и такое легаси.
"ansible_kernel": "6.1.0-40-amd64",
"ansible_kernel_version": "#1 SMP PREEMPT_DYNAMIC Debian 6.1.153-1 (2025-09-20)",
"ansible_lsb": {
"codename": "bookworm",
"description": "Debian GNU/Linux 12 (bookworm)",
"id": "Debian",
"major_release": "12",
"release": "12"

Все вместе выглядит или как начало поиска готового решения «как свернуть xml в набор объектов», или как задача первого (для начинающих) уровня сложности с AlgoMap.io  \ Codility \ LeetCode \ итд, свертывание xml в объект со свойствами.  Не взяв xml.etree.ElementTree, а все сам, все руками. Дело не сложное, но надо вспоминать лаго алгоритм

Но, у меня сейчас дел вдруг привалило, что я даже не знаю, когда дописать цикл. Новый проект, новые задачи.

Поэтому сделаю быстро, грязно, на powershell под windows, и так делать, вообще говоря, не нужно.

Еще придется не забыть сразу сделать выгрузку с примером ошибки недоступности хоста, и что-то с этим делать.

5.4 Разбираем полученную выгрузку

Поскольку все сделано в непревзойденном стиле «давайте не будем спрашивать нейросеть», то не удивляйтесь, что написано не просто плохо, а отвратительно плохо. Ирония не в том, могу ли я сделать задачу «сверните xml в массив вложенных объектов», как на интервью для джуна, а в том, хочу ли я потом искать, в какой путь это свернулось.

Поэтому вот вам еще один образец, как делать плохо и неправильно. Еще и неполный образец. Еще и на Powershell. Короче, сплошной позор.

# Ansible facts parser

Write-Host "Start 01 ================="

$Version = "AFP001"

$ScriptPath = $PSScriptRoot

$DataFromFile001 = Get-Content ($ScriptPath + "\" + "resultv01.txt")

Write-Host 'Read from file total' $DataFromFile001.count

Write-Host 'Read from file first' $DataFromFile001[0]

Write-Host 'Read from file last' $DataFromFile001[$DataFromFile001.count -1]

$SplitStartMark = '| SUCCESS => {'


Write-Host "Start 02 ================="

for ($Mark = 0; $Mark -lt $DataFromFile001.count; $Mark++){

if ($DataFromFile001[$Mark] -like "*$SplitStartMark") {Write-Host "Mark" $Mark ';' $DataFromFile001[$Mark]

}}


Class Split{

[int]$Position

[string]$String

}


Write-Host "Start 03 ================="

$SplitStartMarkPosition = @()


for ($Mark = 0; $Mark -lt $DataFromFile001.count; $Mark++){

if ($DataFromFile001[$Mark] -like "*$SplitStartMark") {

Write-Host "Mark" $Mark ';' $DataFromFile001[$Mark]

$NewHost = [Split]::new()

$NewHost.Position = $Mark

$NewHost.String = $DataFromFile001[$Mark]

$SplitStartMarkPosition += $NewHost

Remove-Variable NewHost

}}

Write-Host "Total" $SplitStartMarkPosition.Count


Write-Host "Start 04 ================="

Class AnsibleFacts01{

[string]$IsSUCCESS

[string]$FQDN

[string]$IP

[string]$ansible_kernel_version}



$NewHost1 = [AnsibleFacts01]::new()

$NewHost1.IsSUCCESS = $DataFromFile001[0]

for ($Mark = 0; $Mark -lt $SplitStartMarkPosition[1].Position; $Mark++){


if ($DataFromFile001[$Mark] -like '*ansible_fqdn*') {$NewHost1.FQDN = $DataFromFile001[$Mark]}

if ($DataFromFile001[$Mark] -like '*ansible_all_ipv4_addresses*') {$NewHost1.IP = $DataFromFile001[$Mark+1]}

if ($DataFromFile001[$Mark] -like '*ansible_kernel_version*') {$NewHost1.ansible_kernel_version = $DataFromFile001[$Mark]}

}


$NewHost1 | fl


Write-Host "Start 05 ================="

$NewHost2 = [AnsibleFacts01]::new()

$NewHost2.IsSUCCESS = $DataFromFile001[$SplitStartMarkPosition[1].Position] -replace "[^a-z][^A-Z]" -replace "{",""

for ($Mark = $SplitStartMarkPosition[1].Position; $Mark -lt $SplitStartMarkPosition[2].Position; $Mark++){

if ($DataFromFile001[$Mark] -like '*ansible_fqdn*') {$NewHost2.FQDN =  $DataFromFile001[$Mark] -replace '"ansible_fqdn":',"" -replace " ", "" -replace ",","" -replace '"',""}

if ($DataFromFile001[$Mark] -like '*ansible_all_ipv4_addresses*') {$NewHost2.IP = ($DataFromFile001[$Mark+1] -replace '"',"").TrimStart()}

$kv = ''

if ($DataFromFile001[$Mark] -like '*ansible_kernel_version*') {$NewHost2.ansible_kernel_version = ($DataFromFile001[$Mark] -replace '"ansible_kernel_version":', ""  -replace "," -replace '"',"").TrimStart()}

}


$NewHost2 | fl

Что делать дальше – понятно. Тут и обработка ошибок, и нормальное формирование объекта, и что делать, если хост не отвечает, и сравнение состояния «как есть» и «как надо».

Заключение
На написание 5 заметок ушло где-то 10-15 дней, по часу в день. Не каждый день. Хотя один выходной я потратил, с обеда до ужина.
На запуск такого костыля «чтобы посмотреть, что там в простой инфраструктуре», зная как, и куда смотреть, ушло бы примерно 3 рабочих дня для 1 джуна. Даже если в инфраструктуре вообще ничего нет. Остальные работы, доведение выгрузки до читаемого вида, сбор образцов, итд, заняли бы еще пару дней с кофе.
Поэтому, если где-то нет такой выгрузки, то я не знаю, чем там занимается и отдел ИТ, и отдел имитации безопасности.

Литература
ahuffman / ansible-sudoers
Ansible docs: ansible
Microsoft: Windows PowerShell - Build User-Friendly XML Interfaces with Windows PowerShell
Microsoft:  Add-Member Module: Microsoft.PowerShell.Utility Module
Microsoft:  Everything you wanted to know about PSCustomObject
Microsoft:  about_Regular_Expressions

Лига Сисадминов

2.7K пост19.2K подписчиков

Правила сообщества

Мы здесь рады любым постам связанным с рабочими буднями специалистов нашей сферы деятельности.

Темы

Политика

Теги

Популярные авторы

Сообщества

18+

Теги

Популярные авторы

Сообщества

Игры

Теги

Популярные авторы

Сообщества

Юмор

Теги

Популярные авторы

Сообщества

Отношения

Теги

Популярные авторы

Сообщества

Здоровье

Теги

Популярные авторы

Сообщества

Путешествия

Теги

Популярные авторы

Сообщества

Спорт

Теги

Популярные авторы

Сообщества

Хобби

Теги

Популярные авторы

Сообщества

Сервис

Теги

Популярные авторы

Сообщества

Природа

Теги

Популярные авторы

Сообщества

Бизнес

Теги

Популярные авторы

Сообщества

Транспорт

Теги

Популярные авторы

Сообщества

Общение

Теги

Популярные авторы

Сообщества

Юриспруденция

Теги

Популярные авторы

Сообщества

Наука

Теги

Популярные авторы

Сообщества

IT

Теги

Популярные авторы

Сообщества

Животные

Теги

Популярные авторы

Сообщества

Кино и сериалы

Теги

Популярные авторы

Сообщества

Экономика

Теги

Популярные авторы

Сообщества

Кулинария

Теги

Популярные авторы

Сообщества

История

Теги

Популярные авторы

Сообщества

Недвижимость и ремонт

Теги

Популярные авторы

Сообщества