--- - name: Post-deploy validation for Windows/RDP AWatch-rus hosts: aw_windows gather_facts: false vars: aw_windows_deploy_root: "C:\\Program Files\\AWatch-rus" aw_windows_state_root: "C:\\ProgramData\\AWatch-rus" aw_windows_validation_remote_path: "{{ aw_windows_state_root }}\\aw_validate_ansible.json" aw_windows_validation_local_dir: "/tmp/aw-rus-validation-{{ lookup('env','USER') | default('ansible', true) }}" aw_windows_server_scheme: "http" aw_windows_server_port: 5600 aw_windows_fail_on_validation_error: true aw_windows_launch_task_pattern: "ActivityWatch Launch *" aw_windows_recovery_task_name: "ActivityWatch Recovery" aw_windows_force_task_restart: true aw_windows_api_smoke_check_enabled: true aw_windows_api_smoke_check_bucket: "" aw_windows_api_smoke_check_limit: 10 aw_windows_api_smoke_check_wait_seconds: 20 tasks: - name: Вычислить inventory host AW server по умолчанию ansible.builtin.set_fact: aw_server_inventory_host_effective: "{{ (groups['aw_server'] | default([]) | first) | default('', true) }}" - name: Вычислить effective host для AW server ansible.builtin.set_fact: aw_windows_server_host_effective: >- {{ aw_windows_server_host | default( ( hostvars[aw_server_inventory_host_effective].ansible_host | default(aw_server_inventory_host_effective, true) ) if (aw_server_inventory_host_effective | length) > 0 else '', true ) }} - name: Вычислить effective каталог health validation на AW server ansible.builtin.set_fact: aw_windows_health_validation_dir_effective: >- {{ ( hostvars[aw_server_inventory_host_effective].aw_rus_health_validation_dir | default('/var/lib/activitywatch/health/windows-validation', true) ) if (aw_server_inventory_host_effective | length) > 0 else '' }} - name: Аккуратно запустить ActivityWatch recovery и launch tasks, если они не в Running when: aw_windows_force_task_restart | bool ansible.windows.win_powershell: script: | $ErrorActionPreference = 'Stop' $recovery = Get-ScheduledTask -TaskName "{{ aw_windows_recovery_task_name }}" -ErrorAction SilentlyContinue if ($recovery -and $recovery.State -notin @('Running', 'Queued')) { Start-ScheduledTask -TaskName "{{ aw_windows_recovery_task_name }}" } Get-ScheduledTask | Where-Object TaskName -like "{{ aw_windows_launch_task_pattern }}" | Where-Object State -notin @('Running', 'Queued') | ForEach-Object { Start-ScheduledTask -TaskName $_.TaskName } - name: Получить Windows hostname для AW smoke-check bucket when: aw_windows_api_smoke_check_enabled | bool ansible.windows.win_command: powershell.exe -NoProfile -Command "$env:COMPUTERNAME" register: aw_windows_hostname_result changed_when: false - name: Вычислить AW AFK smoke-check bucket when: aw_windows_api_smoke_check_enabled | bool ansible.builtin.set_fact: aw_windows_api_smoke_check_bucket_effective: >- {{ aw_windows_api_smoke_check_bucket if (aw_windows_api_smoke_check_bucket | default('') | string | length) > 0 else 'aw-worktime-sessions_' ~ (aw_windows_hostname_result.stdout | trim) }} - name: Дождаться короткого окна стабилизации после перезапуска задач when: aw_windows_api_smoke_check_enabled | bool ansible.builtin.pause: seconds: "{{ aw_windows_api_smoke_check_wait_seconds | int }}" - name: Дождаться свежих worktime-событий на AW server when: aw_windows_api_smoke_check_enabled | bool delegate_to: localhost ansible.builtin.uri: url: "{{ aw_windows_server_scheme }}://{{ aw_windows_server_host_effective }}:{{ aw_windows_server_port }}/api/0/buckets/{{ aw_windows_api_smoke_check_bucket_effective }}/events?limit={{ aw_windows_api_smoke_check_limit }}" method: GET status_code: 200 return_content: true register: aw_windows_api_smoke until: > aw_windows_api_smoke.status == 200 and (aw_windows_api_smoke.json | length) > 0 and ( aw_windows_api_smoke.json | selectattr('data.source', 'equalto', 'worktime-session-collector') | list | length ) > 0 retries: 10 delay: 6 - name: Выполнить валидацию и сохранить отчёт на целевом Windows host ansible.windows.win_powershell: script: | $ErrorActionPreference = 'Stop' $report = & "{{ aw_windows_deploy_root }}\windows\validate-deployment.ps1" ` -ConfigPath "{{ aw_windows_state_root }}\deployment-config.json" $report | ConvertTo-Json -Depth 12 | Out-File -FilePath "{{ aw_windows_validation_remote_path }}" -Encoding utf8 if ({{ '$true' if (aw_windows_fail_on_validation_error | bool) else '$false' }} -and -not [bool]$report.overallOk) { throw "ActivityWatch validation failed. Report: {{ aw_windows_validation_remote_path }}" } - name: Создать локальный каталог для validation reports ansible.builtin.file: path: "{{ aw_windows_validation_local_dir }}" state: directory mode: "0755" delegate_to: localhost - name: Забрать validation report ansible.builtin.fetch: src: "{{ aw_windows_validation_remote_path }}" dest: "{{ aw_windows_validation_local_dir }}/{{ inventory_hostname }}-aw_validate_ansible.json" flat: true - name: Убедиться, что каталог Windows validation существует на AW server when: - aw_server_inventory_host_effective | length > 0 - aw_windows_health_validation_dir_effective | length > 0 ansible.builtin.file: path: "{{ aw_windows_health_validation_dir_effective }}" state: directory mode: "0755" delegate_to: "{{ aw_server_inventory_host_effective }}" - name: Опубликовать validation report на AW server для aw-rus-healthd when: - aw_server_inventory_host_effective | length > 0 - aw_windows_health_validation_dir_effective | length > 0 ansible.builtin.copy: src: "{{ aw_windows_validation_local_dir }}/{{ inventory_hostname }}-aw_validate_ansible.json" dest: "{{ aw_windows_health_validation_dir_effective }}/{{ inventory_hostname }}-aw_validate_ansible.json" mode: "0644" delegate_to: "{{ aw_server_inventory_host_effective }}" - name: Показать путь к отчёту ansible.builtin.debug: msg: - "Validation OK on {{ inventory_hostname }}." - "Report: {{ aw_windows_validation_local_dir }}/{{ inventory_hostname }}-aw_validate_ansible.json"