0783f35e2d
По умолчанию — Статистика: доступность TCP, IP, пользователи, матрица присутствия. Серверы открываются отдельными вкладками. Co-authored-by: Cursor <cursoragent@cursor.com>
165 lines
5.5 KiB
YAML
165 lines
5.5 KiB
YAML
---
|
|
- name: Ensure output root directory exists
|
|
ansible.builtin.file:
|
|
path: "{{ hysteria2_output_dir }}"
|
|
state: directory
|
|
mode: "0700"
|
|
become: false
|
|
|
|
- name: Find server-info.yml in output directories
|
|
ansible.builtin.find:
|
|
paths: "{{ hysteria2_output_dir }}"
|
|
patterns: server-info.yml
|
|
recurse: true
|
|
register: _hysteria2_server_info_files
|
|
become: false
|
|
|
|
- name: Load server metadata from output
|
|
ansible.builtin.slurp:
|
|
src: "{{ item.path }}"
|
|
loop: "{{ _hysteria2_server_info_files.files | default([]) }}"
|
|
register: _hysteria2_server_info_raw
|
|
when: _hysteria2_server_info_files.matched | default(0) | int > 0
|
|
become: false
|
|
|
|
- name: Build global servers list
|
|
ansible.builtin.set_fact:
|
|
hysteria2_global_servers: "{{ hysteria2_global_servers | default([]) + [ _entry ] }}"
|
|
loop: "{{ _hysteria2_server_info_raw.results | default([]) }}"
|
|
when: not item.skipped | default(false)
|
|
vars:
|
|
_info: "{{ item.content | b64decode | from_yaml }}"
|
|
_server_name: "{{ _info.server }}"
|
|
_entry:
|
|
name: "{{ _server_name }}"
|
|
domain: "{{ _info.domain }}"
|
|
port: "{{ _info.port }}"
|
|
mode: "{{ _info.mode | default('masquerade') }}"
|
|
host_ip: >-
|
|
{{
|
|
_info.host_ip
|
|
| default(hostvars[_server_name].ansible_host | default(''), true)
|
|
}}
|
|
dir: "{{ item.item.path | dirname | basename }}"
|
|
users: "{{ _info.users }}"
|
|
become: false
|
|
|
|
- name: Sort global servers by name
|
|
ansible.builtin.set_fact:
|
|
hysteria2_global_servers: "{{ hysteria2_global_servers | sort(attribute='name') }}"
|
|
when: hysteria2_global_servers | default([]) | length > 0
|
|
become: false
|
|
|
|
- name: Probe TCP reachability of exported servers
|
|
ansible.builtin.wait_for:
|
|
host: "{{ item.host_ip if (item.host_ip | default('') | length > 0) else item.domain }}"
|
|
port: "{{ item.port | int }}"
|
|
timeout: 3
|
|
state: started
|
|
loop: "{{ hysteria2_global_servers | default([]) }}"
|
|
loop_control:
|
|
label: "{{ item.name }}"
|
|
register: _hysteria2_probe
|
|
failed_when: false
|
|
changed_when: false
|
|
become: false
|
|
when: hysteria2_global_servers | default([]) | length > 0
|
|
|
|
- name: Merge probe result for each server
|
|
ansible.builtin.set_fact:
|
|
hysteria2_global_servers_enriched: >-
|
|
{{
|
|
(hysteria2_global_servers_enriched | default([]))
|
|
+ [
|
|
hysteria2_global_servers[item] | combine({
|
|
'reachable': not ((_hysteria2_probe.results | default([]))[item].failed | default(true)),
|
|
'probe_seconds': (_hysteria2_probe.results | default([]))[item].elapsed | default(none)
|
|
})
|
|
]
|
|
}}
|
|
loop: "{{ range(0, hysteria2_global_servers | length) | list }}"
|
|
when: hysteria2_global_servers | default([]) | length > 0
|
|
become: false
|
|
|
|
- name: Replace servers list with enriched data
|
|
ansible.builtin.set_fact:
|
|
hysteria2_global_servers: "{{ hysteria2_global_servers_enriched }}"
|
|
when: hysteria2_global_servers_enriched is defined
|
|
become: false
|
|
|
|
- name: Compute unique users across servers
|
|
ansible.builtin.set_fact:
|
|
hysteria2_unique_users: >-
|
|
{{
|
|
hysteria2_global_servers
|
|
| map(attribute='users')
|
|
| map('map', attribute='name')
|
|
| flatten
|
|
| unique
|
|
| sort
|
|
}}
|
|
hysteria2_reachable_count: >-
|
|
{{
|
|
hysteria2_global_servers
|
|
| selectattr('reachable')
|
|
| list
|
|
| length
|
|
}}
|
|
when: hysteria2_global_servers | default([]) | length > 0
|
|
become: false
|
|
|
|
- name: Generate global HTML index
|
|
ansible.builtin.template:
|
|
src: export/global-index.html.j2
|
|
dest: "{{ hysteria2_output_dir }}/index.html"
|
|
mode: "0644"
|
|
vars:
|
|
generated_at: "{{ now(utc=false, fmt='%Y-%m-%d %H:%M:%S') }}"
|
|
total_users: "{{ hysteria2_global_servers | map(attribute='users') | map('length') | sum }}"
|
|
unique_users: "{{ hysteria2_unique_users | default([]) }}"
|
|
reachable_count: "{{ hysteria2_reachable_count | default(0) }}"
|
|
when: hysteria2_global_servers | default([]) | length > 0
|
|
become: false
|
|
|
|
- name: Remove global HTML index when no servers remain
|
|
ansible.builtin.file:
|
|
path: "{{ hysteria2_output_dir }}/index.html"
|
|
state: absent
|
|
when: hysteria2_global_servers | default([]) | length == 0
|
|
become: false
|
|
|
|
- name: Open global index in default browser (macOS)
|
|
ansible.builtin.command:
|
|
cmd: open "{{ hysteria2_output_dir }}/index.html"
|
|
when:
|
|
- hysteria2_open_browser | bool
|
|
- hysteria2_global_servers | default([]) | length > 0
|
|
- ansible_facts['system'] == 'Darwin'
|
|
changed_when: false
|
|
become: false
|
|
|
|
- name: Open global index in default browser (Linux)
|
|
ansible.builtin.command:
|
|
cmd: xdg-open "{{ hysteria2_output_dir }}/index.html"
|
|
when:
|
|
- hysteria2_open_browser | bool
|
|
- hysteria2_global_servers | default([]) | length > 0
|
|
- ansible_facts['system'] == 'Linux'
|
|
changed_when: false
|
|
become: false
|
|
failed_when: false
|
|
|
|
- name: Show global index location
|
|
ansible.builtin.debug:
|
|
msg: >-
|
|
Общий каталог: {{ hysteria2_output_dir }}/index.html
|
|
({% if hysteria2_open_browser | bool and hysteria2_global_servers | default([]) | length > 0 %}открыт в браузере{% else %}откройте вручную{% endif %})
|
|
when: hysteria2_global_servers | default([]) | length > 0
|
|
become: false
|
|
|
|
- name: Skip global index when no servers exported
|
|
ansible.builtin.debug:
|
|
msg: "Глобальный {{ hysteria2_output_dir }}/index.html удалён — нет server-info.yml в output/"
|
|
when: hysteria2_global_servers | default([]) | length == 0
|
|
become: false
|