Обновить playbooks/inventory.yml

This commit is contained in:
2025-12-10 10:01:13 +00:00
parent 4a6c0f3d4c
commit 3443977c6d

View File

@@ -1,107 +1,86 @@
--- ---
- name: Сбор инвентаря и создание его в Semaphore UI - name: Сбор инвентаря и создание (Метод через файл)
hosts: localhost hosts: localhost
connection: local connection: local
gather_facts: no gather_facts: no
vars: vars:
# --- НАСТРОЙКИ SEMAPHORE --- # --- НАСТРОЙКИ ---
semaphore_url: "http://192.168.0.198:9999" # Укажите ваш URL (или http://localhost:3000) semaphore_url: "http://192.168.0.198:9999"
semaphore_project_id: 1 semaphore_project_id: 1
# ID ключа, который будет использоваться для подключения к новым хостам
semaphore_key_id: 7 semaphore_key_id: 7
# Токен API (лучше хранить в Secret, но для теста можно тут)
semaphore_api_token: "9ojexqiwt1xkemig7j1bd1pe-frh7hkre4reryk2occ=" semaphore_api_token: "9ojexqiwt1xkemig7j1bd1pe-frh7hkre4reryk2occ="
inventory_name: "Auto Scanned Network" inventory_name: "Auto Scanned Network"
# --- НАСТРОЙКИ СЕТИ --- # --- СЕТИ ---
subnets: subnets:
- "192.168.0.0/24" - "192.168.0.0/23"
- "192.168.1.0/24" - "192.168.1.0/23"
- "192.168.2.0/24" - "192.168.2.0/24"
- "192.168.3.0/24" - "192.168.3.0/24"
- "172.19.8.0/23" - "172.19.8.0/24"
- "172.19.9.0/23" - "172.19.9.0/24"
- "172.19.10.0/23" - "172.19.10.0/24"
- "172.19.24.0/23" - "172.19.24.0/24"
- "172.19.26.0/23" - "172.19.26.0/24"
- "172.19.40.0/23" - "172.19.40.0/24"
- "172.19.42.0/23" - "172.19.42.0/24"
- "172.19.56.0/23" - "172.19.56.0/24"
- "172.19.58.0/23" - "172.19.58.0/24"
- "172.19.90.0/23" - "172.19.90.0/24"
# - "192.168.1.0/24" # Добавьте нужные подсети # добавьте остальные ваши подсети сюда...
scan_ports: [5985, 22, 445] scan_ports: [5985, 22, 445]
tasks: tasks:
# --------------------------------------------------------- # 1. Сканирование (Ваш код)
# ШАГ 1: Сканирование (Nmap) - name: Сканирование сети
# ---------------------------------------------------------
- name: Сканирование сети (поиск живых IP)
command: > command: >
nmap -p {{ scan_ports | join(',') }} nmap -p {{ scan_ports | join(',') }}
-Pn -n --open --min-rate 1000 -T4 -oG - -Pn -n --open --min-rate 1000 -T4 -oG -
{{ subnets | join(' ') }} {{ subnets | join(' ') }}
register: nmap_result register: nmap_result
changed_when: false changed_when: false
ignore_errors: yes # Чтобы не падало, если ничего не нашлось ignore_errors: yes
- name: Извлечение IP адресов - name: Извлечение IP
set_fact: set_fact:
active_ips: "{{ nmap_result.stdout | regex_findall('Host: ([0-9.]+).*Ports:.*(?:' + scan_ports | join('|') + ')/open') | unique | list }}" active_ips: "{{ nmap_result.stdout | regex_findall('Host: ([0-9.]+).*Ports:.*(?:' + scan_ports | join('|') + ')/open') | unique | list }}"
- name: Проверка, найдены ли IP - name: Проверка IP
fail: fail:
msg: "Не найдено ни одного активного IP. Проверьте настройки сети или Nmap." msg: "IP не найдены!"
when: active_ips | length == 0 when: active_ips | length == 0
# --------------------------------------------------------- # 2. Имена (Ваш код)
# ШАГ 2: Определение имен - name: Определение имен
# ---------------------------------------------------------
- name: Определение имен хостов (SMB Discovery + DNS)
shell: | shell: |
IP="{{ item }}" IP="{{ item }}"
SMB_NAME=$(nmap -p 445 --script smb-os-discovery $IP -Pn -n | grep "Computer name:" | awk -F': ' '{print $2}') SMB_NAME=$(nmap -p 445 --script smb-os-discovery $IP -Pn -n | grep "Computer name:" | awk -F': ' '{print $2}')
if [ ! -z "$SMB_NAME" ]; then if [ ! -z "$SMB_NAME" ]; then echo "$SMB_NAME" | tr '[:upper:]' '[:lower:]'; else
echo "$SMB_NAME" | tr '[:upper:]' '[:lower:]'
else
DNS_NAME=$(nslookup -timeout=1 $IP 192.168.1.250 2>/dev/null | grep 'name =' | awk '{print $NF}' | sed 's/\.$//' | head -n 1) DNS_NAME=$(nslookup -timeout=1 $IP 192.168.1.250 2>/dev/null | grep 'name =' | awk '{print $NF}' | sed 's/\.$//' | head -n 1)
if [ ! -z "$DNS_NAME" ]; then if [ ! -z "$DNS_NAME" ]; then echo "$DNS_NAME" | tr '[:upper:]' '[:lower:]'; else echo "UNKNOWN"; fi
echo "$DNS_NAME" | tr '[:upper:]' '[:lower:]'
else
echo "UNKNOWN"
fi
fi fi
loop: "{{ active_ips }}" loop: "{{ active_ips }}"
register: host_names register: host_names
changed_when: false changed_when: false
no_log: true no_log: true
# --------------------------------------------------------- # 3. Сортировка (Ваш код)
# ШАГ 3: Сортировка и генерация текста - name: Сортировка
# ---------------------------------------------------------
- name: Сортировка хостов
set_fact: set_fact:
pc_list: >- pc_list: >-
{{ host_names.results | selectattr('stdout', 'search', 'pc') {{ host_names.results | selectattr('stdout', 'search', 'pc') | map(attribute='item') | list | zip(host_names.results | selectattr('stdout', 'search', 'pc') | map(attribute='stdout') | list) | list }}
| map(attribute='item') | list
| zip(host_names.results | selectattr('stdout', 'search', 'pc') | map(attribute='stdout') | list)
| list }}
other_list: >- other_list: >-
{{ host_names.results | rejectattr('stdout', 'search', 'pc') {{ host_names.results | rejectattr('stdout', 'search', 'pc') | map(attribute='item') | list | zip(host_names.results | rejectattr('stdout', 'search', 'pc') | map(attribute='stdout') | list) | list }}
| map(attribute='item') | list
| zip(host_names.results | rejectattr('stdout', 'search', 'pc') | map(attribute='stdout') | list)
| list }}
- name: Генерация текста инвентаря # 4. Текст инвентаря
- name: Генерация текста
set_fact: set_fact:
inventory_content: | inventory_content: |
# === Найденные PC ===
[windows_pcs] [windows_pcs]
{% for ip, name in pc_list %} {% for ip, name in pc_list %}
{{ name }} ansible_host={{ ip }} {{ name }} ansible_host={{ ip }}
{% endfor %} {% endfor %}
# === Остальные устройства ===
[windows_other] [windows_other]
{% for ip, name in other_list %} {% for ip, name in other_list %}
{% if name == "UNKNOWN" %} {% if name == "UNKNOWN" %}
@@ -121,54 +100,43 @@
ansible_shell_type=powershell ansible_shell_type=powershell
ansible_user=o.grechko ansible_user=o.grechko
# --------------------------------------------------------- # ==========================================================
# ШАГ 4: Отладка (проверка данных перед отправкой) # ИЗМЕНЕННАЯ ЧАСТЬ: СОЗДАНИЕ ЧЕРЕЗ ФАЙЛ
# --------------------------------------------------------- # ==========================================================
- name: Debug Payload (Проверка данных)
- name: Сохранение JSON-пейлоада в файл (для надежности)
copy:
content: |
{
"name": "{{ inventory_name }} {{ 1000 | random }}",
"project_id": {{ semaphore_project_id | int }},
"type": "static",
"ssh_key_id": {{ semaphore_key_id | int }},
"become_key_id": null,
"repository_id": null,
"inventory": {{ inventory_content | to_json }}
}
dest: /tmp/semaphore_payload.json
- name: Отправка через CURL (чтение из файла)
command: >
curl -v -X POST "{{ semaphore_url }}/api/project/{{ semaphore_project_id }}/inventory"
-H "Authorization: Bearer {{ semaphore_api_token }}"
-H "Content-Type: application/json"
-H "Accept: application/json"
-d @/tmp/semaphore_payload.json
register: curl_result
ignore_errors: yes
- name: Показать полный ответ CURL
debug: debug:
msg: var: curl_result.stderr_lines
- "URL: {{ semaphore_url }}/api/project/{{ semaphore_project_id }}/inventory"
- "SSH Key ID: {{ semaphore_key_id }}"
- "Количество символов в инвентаре: {{ inventory_content | length }}"
# --------------------------------------------------------- - name: Показать ответ сервера (body)
# ШАГ 5: Отправка в API (ИСПРАВЛЕНО ssh_key_id)
# ---------------------------------------------------------
- name: Создание инвентаря в Semaphore через API
uri:
url: "{{ semaphore_url }}/api/project/{{ semaphore_project_id }}/inventory"
method: POST
headers:
Authorization: "Bearer {{ semaphore_api_token }}"
Content-Type: "application/json"
Accept: "application/json"
body_format: json
body:
# Добавляем рандом, чтобы имя было уникальным при каждом запуске
name: "{{ inventory_name }} {{ 10000 | random }}"
project_id: "{{ semaphore_project_id | int }}"
type: "static"
ssh_key_id: "{{ semaphore_key_id | int }}"
become_key_id: null
# !!! ВОТ ЭТО ПОЛЕ ОБЯЗАТЕЛЬНО !!!
repository_id: null
inventory: "{{ inventory_content }}"
status_code: [201, 200]
register: api_response
ignore_errors: yes # Чтобы увидеть вывод ошибки, если она случится
# Эта задача покажет, ПОЧЕМУ именно сервер ругается (текст ошибки)
- name: ОТЛАДКА - Ответ сервера (если ошибка)
debug: debug:
msg: "Server response: {{ api_response.json | default(api_response.content) }}" var: curl_result.stdout_lines
when: api_response.failed is defined and api_response.failed
- name: Остановка сценария при ошибке - name: Удалить временный файл
fail: file:
msg: "Не удалось создать инвентарь. См. причину выше." path: /tmp/semaphore_payload.json
when: api_response.failed is defined and api_response.failed state: absent
- name: Успех
debug:
msg: "Инвентарь создан! ID: {{ api_response.json.id }}"
when: api_response.status == 201 or api_response.status == 200