--- - name: Сбор инвентаря и создание его в Semaphore UI hosts: localhost connection: local gather_facts: no vars: # --- НАСТРОЙКИ SEMAPHORE --- semaphore_url: "http://192.168.0.198:9999" # Укажите ваш URL (или http://localhost:3000) semaphore_project_id: 1 # ID ключа, который будет использоваться для подключения к новым хостам semaphore_key_id: 7 # Токен API (лучше хранить в Secret, но для теста можно тут) semaphore_api_token: "9ojexqiwt1xkemig7j1bd1pe-frh7hkre4reryk2occ=" inventory_name: "Auto Scanned Network" # --- НАСТРОЙКИ СЕТИ --- subnets: - "192.168.0.0/24" - "192.168.1.0/24" - "192.168.2.0/24" - "192.168.3.0/24" - "172.19.8.0/23" - "172.19.9.0/23" - "172.19.10.0/23" - "172.19.24.0/23" - "172.19.26.0/23" - "172.19.40.0/23" - "172.19.42.0/23" - "172.19.56.0/23" - "172.19.58.0/23" - "172.19.90.0/23" # - "192.168.1.0/24" # Добавьте нужные подсети scan_ports: [5985, 22, 445] tasks: # --------------------------------------------------------- # ШАГ 1: Сканирование (Nmap) # --------------------------------------------------------- - name: Сканирование сети (поиск живых IP) command: > nmap -p {{ scan_ports | join(',') }} -Pn -n --open --min-rate 1000 -T4 -oG - {{ subnets | join(' ') }} register: nmap_result changed_when: false ignore_errors: yes # Чтобы не падало, если ничего не нашлось - name: Извлечение IP адресов set_fact: active_ips: "{{ nmap_result.stdout | regex_findall('Host: ([0-9.]+).*Ports:.*(?:' + scan_ports | join('|') + ')/open') | unique | list }}" - name: Проверка, найдены ли IP fail: msg: "Не найдено ни одного активного IP. Проверьте настройки сети или Nmap." when: active_ips | length == 0 # --------------------------------------------------------- # ШАГ 2: Определение имен # --------------------------------------------------------- - name: Определение имен хостов (SMB Discovery + DNS) shell: | IP="{{ item }}" SMB_NAME=$(nmap -p 445 --script smb-os-discovery $IP -Pn -n | grep "Computer name:" | awk -F': ' '{print $2}') if [ ! -z "$SMB_NAME" ]; then 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) if [ ! -z "$DNS_NAME" ]; then echo "$DNS_NAME" | tr '[:upper:]' '[:lower:]' else echo "UNKNOWN" fi fi loop: "{{ active_ips }}" register: host_names changed_when: false no_log: true # --------------------------------------------------------- # ШАГ 3: Сортировка и генерация текста # --------------------------------------------------------- - name: Сортировка хостов set_fact: pc_list: >- {{ host_names.results | selectattr('stdout', 'search', 'pc') | map(attribute='item') | list | zip(host_names.results | selectattr('stdout', 'search', 'pc') | map(attribute='stdout') | list) | list }} other_list: >- {{ host_names.results | rejectattr('stdout', 'search', 'pc') | map(attribute='item') | list | zip(host_names.results | rejectattr('stdout', 'search', 'pc') | map(attribute='stdout') | list) | list }} - name: Генерация текста инвентаря set_fact: inventory_content: | # === Найденные PC === [windows_pcs] {% for ip, name in pc_list %} {{ name }} ansible_host={{ ip }} {% endfor %} # === Остальные устройства === [windows_other] {% for ip, name in other_list %} {% if name == "UNKNOWN" %} unknown_{{ ip | replace('.', '_') }} ansible_host={{ ip }} {% else %} {{ name }} ansible_host={{ ip }} {% endif %} {% endfor %} [windows:children] windows_pcs windows_other [windows:vars] ansible_connection=ssh ansible_port=22 ansible_shell_type=powershell ansible_user=o.grechko # --------------------------------------------------------- # ШАГ 4: Отладка (проверка данных перед отправкой) # --------------------------------------------------------- - name: Debug Payload (Проверка данных) debug: msg: - "URL: {{ semaphore_url }}/api/project/{{ semaphore_project_id }}/inventory" - "SSH Key ID: {{ semaphore_key_id }}" - "Количество символов в инвентаре: {{ inventory_content | length }}" # --------------------------------------------------------- # ШАГ 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 }}" project_id: "{{ semaphore_project_id | int }}" type: "static" ssh_key_id: "{{ semaphore_key_id | int }}" become_key_id: null inventory: "{{ inventory_content }}" status_code: [201, 200] register: api_response - name: Успех debug: msg: "Инвентарь создан! ID: {{ api_response.json.id | default('OK') }}"