Files
AWatch-rus/ansible/deploy_aw_server.yml
T

2622 lines
112 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
- name: Развернуть сервер AWatch-rus
hosts: aw_server
become: true
gather_facts: true
vars:
aw_release_root: "/opt/activitywatch/releases"
aw_release_dir: "{{ aw_release_root }}/{{ aw_server_version }}"
aw_archive_path: "/tmp/activitywatch-{{ aw_server_version }}.zip"
aw_bootstrap_dir: "/tmp/aw-rus-bootstrap"
aw_release_install_dir: "{{ aw_release_root }}/aw-server-rust-{{ aw_server_version }}"
aw_ru_patch_cache_bust: "{{ lookup('file', aw_repo_root + '/aw-server/aw-ru-patch.js') | hash('sha1') | truncate(12, true, '') }}"
aw_sw_cleanup_cache_bust: "{{ lookup('file', aw_repo_root + '/aw-server/aw-sw-cleanup.js') | hash('sha1') | truncate(12, true, '') }}"
aw_worktime_classes: "{{ lookup('file', aw_repo_root + '/aw-server/settings/classes-worktime.json') | from_json }}"
aw_default_views: "{{ lookup('file', aw_repo_root + '/aw-server/settings/views-default.json') | from_json }}"
aw_rust_release_dir: "{{ (lookup('env', 'CARGO_TARGET_DIR') | default(aw_repo_root + '/adk-rust/target', true)) + '/release' }}"
tasks:
- name: Установить базовые пакеты
ansible.builtin.apt:
name:
- curl
- python3-venv
- python3-pip
- rsync
- tesseract-ocr
- tesseract-ocr-rus
- unzip
- jq
state: present
update_cache: true
- name: Установить пакеты для browser smoke проверки
ansible.builtin.apt:
name:
- chromium
- nodejs
- node-playwright
state: present
when: aw_browser_smoke_enabled | default(true) | bool
- name: Создать системную группу сервиса
ansible.builtin.group:
name: "{{ aw_server_group }}"
system: true
state: present
- name: Создать системную учётную запись сервиса
ansible.builtin.user:
name: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
home: "{{ aw_server_data_dir }}"
shell: /usr/sbin/nologin
system: true
create_home: false
- name: Создать обязательные каталоги
ansible.builtin.file:
path: "{{ item }}"
state: directory
mode: "0755"
loop:
- "{{ aw_release_root }}"
- "{{ aw_release_dir }}"
- "{{ aw_release_install_dir }}"
- /opt/activitywatch
- /opt/activitywatch/bin
- "{{ aw_server_webui_dir }}"
- "{{ aw_server_webui_dir }}/js"
- "{{ aw_server_data_dir }}"
- "{{ aw_server_db_path | dirname }}"
- "{{ aw_server_data_dir }}/.config"
- "{{ aw_server_data_dir }}/.config/activitywatch"
- "{{ aw_server_data_dir }}/.config/activitywatch/aw-server-rust"
- "{{ aw_server_data_dir }}/backups"
- "{{ aw_server_data_dir }}/slo"
- "{{ aw_server_data_dir }}/browser-smoke"
- "{{ aw_rus_health_state_dir }}"
- "{{ aw_rus_health_validation_dir }}"
- "{{ aw_server_log_dir }}"
- /etc/activitywatch
- /usr/local/lib/aw-rus-browser-smoke
- "{{ aw_bootstrap_dir }}"
- name: Настроить каталоги ActivityWatch с владельцем сервиса
ansible.builtin.file:
path: "{{ item }}"
state: directory
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
mode: "0755"
loop:
- /opt/activitywatch
- /opt/activitywatch/bin
- "{{ aw_release_root }}"
- "{{ aw_release_dir }}"
- "{{ aw_release_install_dir }}"
- "{{ aw_server_webui_dir }}"
- "{{ aw_server_webui_dir }}/js"
- "{{ aw_server_data_dir }}"
- "{{ aw_server_db_path | dirname }}"
- "{{ aw_server_data_dir }}/.config"
- "{{ aw_server_data_dir }}/.config/activitywatch"
- "{{ aw_server_data_dir }}/.config/activitywatch/aw-server-rust"
- "{{ aw_server_data_dir }}/backups"
- "{{ aw_server_data_dir }}/slo"
- "{{ aw_server_data_dir }}/browser-smoke"
- "{{ aw_rus_health_state_dir }}"
- "{{ aw_rus_health_validation_dir }}"
- "{{ aw_server_log_dir }}"
- name: Проверить существующие health state files
ansible.builtin.stat:
path: "{{ item }}"
loop:
- "{{ aw_rus_health_state_dir }}/aw-rus-health.json"
- "{{ aw_rus_health_state_dir }}/aw-rus-health.txt"
- "{{ aw_rus_health_state_dir }}/dlp-health-check-counters.json"
register: aw_rus_health_state_files
- name: Нормализовать владельца существующих health state files
ansible.builtin.file:
path: "{{ item.stat.path }}"
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
mode: "0644"
loop: "{{ aw_rus_health_state_files.results }}"
when: item.stat.exists | default(false)
- name: Удалить устаревшие Python entrypoints после Rust migration
ansible.builtin.file:
path: "{{ item }}"
state: absent
loop:
- /opt/activitywatch/aw-rus-ops/health-check.sh
- /opt/activitywatch/aw-rus-ops/hayabusa/aw-hayabusa-autoprocess.py
- /opt/activitywatch/aw-rus-ops/hayabusa/aw-hayabusa-case-alert.py
- /opt/activitywatch/aw-rus-ops/hayabusa/aw-hayabusa-from-windows.py
- /opt/activitywatch/aw-rus-ops/hayabusa/aw-hayabusa-link-case.py
- /opt/activitywatch/dlp-case-management/.venv
- /opt/activitywatch/dlp-case-management/case_rules.py
- /opt/activitywatch/dlp-case-management/case_schema.py
- /opt/activitywatch/dlp-case-management/case_service.py
- /opt/activitywatch/dlp-case-management/case_storage.py
- /opt/activitywatch/dlp-case-management/evidence_chain.py
- /opt/activitywatch/dlp-compliance/compliance_scheduler.py
- /opt/activitywatch/dlp-compliance/report_generator.py
- /opt/activitywatch/dlp-compliance/.venv
- /opt/activitywatch/dlp-integrations/cef_exporter.py
- /opt/activitywatch/dlp-integrations/syslog_forwarder.py
- /opt/activitywatch/dlp-integrations/webhook_sender.py
- /opt/activitywatch/dlp-integrations/.venv
- /opt/activitywatch/dlp-policy-engine/.venv
- /opt/activitywatch/dlp-policy-engine/policy_distributor.py
- /opt/activitywatch/dlp-policy-engine/policy_schema.py
- /opt/activitywatch/dlp-policy-engine/policy_service.py
- /opt/activitywatch/dlp-policy-engine/policy_storage.py
- /opt/activitywatch/scripts/aggregate_dlp_events.py
- /usr/local/bin/aw-dlp-influx-exporter.py
- /usr/local/bin/aw-extract-ioc-from-sigma.py
- /usr/local/bin/aw-rus-healthd.py
- /usr/local/bin/aw-slo-monitor.py
- /usr/local/bin/aw-worktime-afk-bridge.py
- /usr/local/bin/aw-worktime-api.py
- /usr/local/bin/aw-worktime-influx-exporter.py
- /usr/local/bin/aw-worktime-ui-bridge.py
- /usr/local/bin/dlp-admin-cli.py
- /usr/local/bin/merge_aw_server_dbs.py
- name: Установить prune script для локального state
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/aw-prune-local-state.sh"
dest: /usr/local/bin/aw-prune-local-state.sh
owner: root
group: root
mode: "0755"
- name: Положить legacy prune script в server-side ops bundle
ansible.builtin.copy:
src: "{{ aw_repo_root }}/scripts/legacy/aw-prune-local-state.sh"
dest: /opt/activitywatch/aw-rus-ops/aw-prune-local-state.sh
owner: root
group: root
mode: "0755"
- name: Проверить локальный Rust prune local state
ansible.builtin.stat:
path: "{{ aw_rust_release_dir }}/aw-prune-local-state"
delegate_to: localhost
register: aw_prune_local_state_rust_binary
become: false
- name: Установить Rust prune local state
ansible.builtin.copy:
src: "{{ aw_rust_release_dir }}/aw-prune-local-state"
dest: /usr/local/bin/aw-prune-local-state-rust
owner: root
group: root
mode: "0755"
when: aw_prune_local_state_rust_binary.stat.exists | default(false)
- name: Ограничить рост journald на aw-server
ansible.builtin.copy:
dest: /etc/systemd/journald.conf.d/aw-rus-retention.conf
owner: root
group: root
mode: "0644"
content: |
[Journal]
SystemMaxUse={{ aw_server_journal_system_max_use }}
RuntimeMaxUse={{ aw_server_journal_runtime_max_use }}
SystemKeepFree={{ aw_server_journal_system_keep_free }}
register: aw_journald_dropin
- name: Установить systemd service prune локального state
ansible.builtin.copy:
dest: /etc/systemd/system/aw-prune-local-state.service
owner: root
group: root
mode: "0644"
content: |
[Unit]
Description=Prune ActivityWatch local backups and temp state
[Service]
Type=oneshot
Environment=AW_DATA_DIR={{ aw_server_data_dir }}
Environment=AW_BACKUP_RETENTION_DAYS={{ aw_server_backup_retention_days }}
Environment=AW_BACKUP_KEEP_LAST_DB={{ aw_server_backup_keep_last_db }}
Environment=AW_BACKUP_KEEP_LAST_JSON={{ aw_server_backup_keep_last_json }}
ExecStart=/usr/local/bin/aw-prune-local-state.sh
- name: Установить systemd timer prune локального state
ansible.builtin.copy:
dest: /etc/systemd/system/aw-prune-local-state.timer
owner: root
group: root
mode: "0644"
content: |
[Unit]
Description=Daily prune of ActivityWatch local backups and temp state
[Timer]
OnCalendar=*-*-* 04:40:00
Persistent=true
[Install]
WantedBy=timers.target
- name: Перечитать systemd после retention unit/drop-in
ansible.builtin.systemd:
daemon_reload: true
- name: Включить и запустить timer prune локального state
ansible.builtin.systemd:
name: aw-prune-local-state.timer
enabled: true
state: started
- name: Применить journald retention без простоя
ansible.builtin.command:
argv:
- systemctl
- restart
- systemd-journald
when: aw_journald_dropin.changed
failed_when: false
- name: Сжать существующий journald до нового лимита
ansible.builtin.command:
argv:
- journalctl
- --vacuum-size={{ aw_server_journal_system_max_use }}
changed_when: true
failed_when: false
- name: (Check mode) Пропустить установку релиза ActivityWatch
ansible.builtin.debug:
msg: "ansible_check_mode=true: download/unarchive/install of ActivityWatch release is skipped."
when: ansible_check_mode
- name: Установить релиз ActivityWatch (download/unarchive/install)
when: not ansible_check_mode
block:
- name: Скачать архив релиза ActivityWatch
ansible.builtin.get_url:
url: "{{ aw_server_download_url }}"
dest: "{{ aw_archive_path }}"
mode: "0644"
- name: Распаковать релиз ActivityWatch
ansible.builtin.unarchive:
src: "{{ aw_archive_path }}"
dest: "{{ aw_release_dir }}"
remote_src: true
extra_opts: ["-o"]
- name: Удалить временный архив ActivityWatch после распаковки
ansible.builtin.file:
path: "{{ aw_archive_path }}"
state: absent
- name: Найти распакованный каталог ActivityWatch
ansible.builtin.find:
paths: "{{ aw_release_dir }}"
recurse: true
file_type: directory
patterns: "activitywatch*"
register: aw_release_find
- name: Найти бинарный файл AW server
ansible.builtin.find:
paths: "{{ aw_release_dir }}"
recurse: true
file_type: file
patterns:
- aw-server-rust
- aw-server
register: aw_server_binary_find
- name: Найти index.html WebUI
ansible.builtin.find:
paths: "{{ aw_release_dir }}"
recurse: true
file_type: file
patterns:
- index.html
register: aw_webui_index_find
- name: Сохранить пути распакованного релиза (binary + webui index)
ansible.builtin.set_fact:
aw_release_extracted: "{{ (aw_release_find.files | default([]) | sort(attribute='path') | map(attribute='path') | list | first) | default('') }}"
aw_server_binary_path: >-
{{
(
(
(aw_server_binary_find.files | default([]) | sort(attribute='path') | map(attribute='path') | list)
| select('match', '.*/aw-server-rust$') | list | first
)
| default(
(
(aw_server_binary_find.files | default([]) | sort(attribute='path') | map(attribute='path') | list | first)
),
true
)
) | default('')
}}
aw_webui_index_path: >-
{{
(
(
(aw_webui_index_find.files | default([]) | sort(attribute='path') | map(attribute='path') | list)
| select('search', '/static/index\\.html$') | list | first
)
| default(
(
(aw_webui_index_find.files | default([]) | sort(attribute='path') | map(attribute='path') | list | first)
),
true
)
) | default('')
}}
- name: Сохранить каталог WebUI (dirname index.html)
ansible.builtin.set_fact:
aw_webui_source_path: "{{ aw_webui_index_path | dirname }}"
- name: Проверить, что компоненты релиза найдены
ansible.builtin.assert:
that:
- aw_release_extracted is defined
- aw_release_extracted | length > 0
- aw_server_binary_path is defined
- aw_server_binary_path | length > 0
- aw_webui_source_path is defined
- aw_webui_source_path | length > 0
fail_msg: "Не удалось найти бинарный файл или WebUI в распакованном релизе ActivityWatch."
- name: Создать каталог установленного релиза
ansible.builtin.file:
path: "{{ aw_release_install_dir }}"
state: directory
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
mode: "0755"
- name: Установить бинарный файл AW server
ansible.builtin.copy:
remote_src: true
src: "{{ aw_server_binary_path }}"
dest: "{{ aw_release_install_dir }}/aw-server-rust"
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
mode: "0755"
- name: Создать ссылку на активный бинарный файл AW server
ansible.builtin.file:
src: "{{ aw_release_install_dir }}/aw-server-rust"
dest: /opt/activitywatch/bin/aw-server-rust
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
state: link
force: true
- name: Синхронизировать WebUI в RU каталог
ansible.builtin.command:
cmd: "rsync -a {{ aw_webui_source_path }}/ {{ aw_server_webui_dir }}/"
- name: Настроить владельца файлов /opt/activitywatch
ansible.builtin.file:
path: /opt/activitywatch
state: directory
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
recurse: true
- name: Установить systemd service из шаблона репозитория
ansible.builtin.copy:
dest: /etc/systemd/system/activitywatch-server.service
mode: "0644"
content: >-
{{
lookup('file', aw_repo_root + '/aw-server/activitywatch-server.service')
| replace('__AW_SERVER_USER__', aw_server_user)
| replace('__AW_SERVER_GROUP__', aw_server_group)
| replace('__AW_SERVER_DATA_DIR__', aw_server_data_dir)
}}
notify:
- Перезагрузить systemd
- Перезапустить activitywatch
- name: (Check mode) Пропустить WebUI patch и запуск сервиса
ansible.builtin.debug:
msg: "ansible_check_mode=true: WebUI patch + service start + API checks are skipped."
when: ansible_check_mode
- name: Применить WebUI RU patch и запустить сервис
when: not ansible_check_mode
block:
- name: Скопировать RU patch файлы WebUI из репозитория
ansible.builtin.copy:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
mode: "{{ item.mode }}"
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
loop:
- { src: "{{ aw_repo_root }}/aw-server/aw-ru-patch.js", dest: "{{ aw_server_webui_dir }}/js/ru-patch-v5.js", mode: "0644" }
- { src: "{{ aw_repo_root }}/aw-server/aw-sw-cleanup.js", dest: "{{ aw_server_webui_dir }}/js/sw-cleanup.js", mode: "0644" }
- { src: "{{ aw_repo_root }}/aw-server/aw-worktime-panel.js", dest: "{{ aw_server_webui_dir }}/js/aw-worktime-panel.js", mode: "0644" }
- { src: "{{ aw_repo_root }}/aw-server/aw-host-groups.json", dest: "{{ aw_server_webui_dir }}/js/aw-host-groups.json", mode: "0644" }
- name: Создать каталог /opt/detmir/bootstrap для apply_webui_ru_patch.sh
ansible.builtin.file:
path: /opt/detmir/bootstrap
state: directory
mode: "0755"
- name: Скопировать RU patch файлы для apply_webui_ru_patch.sh (хотфиксы compiled JS чанков)
ansible.builtin.copy:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
mode: "{{ item.mode }}"
loop:
- { src: "{{ aw_repo_root }}/aw-server/aw-ru-patch.js", dest: "/opt/detmir/bootstrap/aw-ru-patch.js", mode: "0644" }
- { src: "{{ aw_repo_root }}/aw-server/aw-sw-cleanup.js", dest: "/opt/detmir/bootstrap/aw-sw-cleanup.js", mode: "0644" }
- { src: "{{ aw_repo_root }}/aw-server/aw-worktime-panel.js", dest: "/opt/detmir/bootstrap/aw-worktime-panel.js", mode: "0644" }
- { src: "{{ aw_repo_root }}/aw-server/aw-host-groups.json", dest: "/opt/detmir/bootstrap/aw-host-groups.json", mode: "0644" }
- name: Скопировать apply_webui_ru_patch.sh скрипт
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/apply_webui_ru_patch.sh"
dest: /opt/activitywatch/aw-server/apply_webui_ru_patch.sh
mode: "0755"
- name: Создать server-side ops bundle для ранних health helpers
ansible.builtin.file:
path: /opt/activitywatch/aw-rus-ops
state: directory
owner: root
group: root
mode: "0755"
- name: Установить wrapper aw-health-check до Influx проверок
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/aw-health-check-wrapper.sh"
dest: /usr/local/bin/aw-health-check
owner: root
group: root
mode: "0755"
- name: Проверить локальный Rust aw-health-check до Influx проверок
ansible.builtin.stat:
path: "{{ aw_rust_release_dir }}/aw-health-check"
delegate_to: localhost
register: aw_health_check_rust_binary_early
become: false
- name: Установить Rust aw-health-check до Influx проверок
ansible.builtin.copy:
src: "{{ aw_rust_release_dir }}/aw-health-check"
dest: /usr/local/bin/aw-health-check-rust
owner: root
group: root
mode: "0755"
when: aw_health_check_rust_binary_early.stat.exists | default(false)
- name: Требовать Rust aw-health-check до Influx проверок
ansible.builtin.assert:
that:
- aw_health_check_rust_binary_early.stat.exists | default(false)
fail_msg: "Rust aw-health-check artifact is required at {{ aw_rust_release_dir }}/aw-health-check"
- name: Проверить локальный Rust aw-db-health до Influx проверок
ansible.builtin.stat:
path: "{{ aw_rust_release_dir }}/aw-db-health"
delegate_to: localhost
register: aw_db_health_rust_binary_early
become: false
- name: Установить Rust aw-db-health до Influx проверок
ansible.builtin.copy:
src: "{{ aw_rust_release_dir }}/aw-db-health"
dest: /usr/local/bin/aw-db-health
owner: root
group: root
mode: "0755"
when: aw_db_health_rust_binary_early.stat.exists | default(false)
- name: Проверить локальный Rust aw-ensure-reliability до Influx проверок
ansible.builtin.stat:
path: "{{ aw_rust_release_dir }}/aw-ensure-reliability"
delegate_to: localhost
register: aw_ensure_reliability_rust_binary_early
become: false
- name: Установить Rust aw-ensure-reliability до Influx проверок
ansible.builtin.copy:
src: "{{ aw_rust_release_dir }}/aw-ensure-reliability"
dest: /usr/local/bin/aw-ensure-reliability
owner: root
group: root
mode: "0755"
when: aw_ensure_reliability_rust_binary_early.stat.exists | default(false)
- name: Проверить локальный Rust aw-db-maintenance до Influx проверок
ansible.builtin.stat:
path: "{{ aw_rust_release_dir }}/aw-db-maintenance"
delegate_to: localhost
register: aw_db_maintenance_rust_binary_early
become: false
- name: Установить Rust aw-db-maintenance до Influx проверок
ansible.builtin.copy:
src: "{{ aw_rust_release_dir }}/aw-db-maintenance"
dest: /usr/local/bin/aw-db-maintenance
owner: root
group: root
mode: "0755"
when: aw_db_maintenance_rust_binary_early.stat.exists | default(false)
- name: Установить aw-db-maintenance service до Influx проверок
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/aw-db-maintenance.service"
dest: /etc/systemd/system/aw-db-maintenance.service
owner: root
group: root
mode: "0644"
when: aw_db_maintenance_rust_binary_early.stat.exists | default(false)
- name: Установить aw-db-maintenance timer до Influx проверок
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/aw-db-maintenance.timer"
dest: /etc/systemd/system/aw-db-maintenance.timer
owner: root
group: root
mode: "0644"
when: aw_db_maintenance_rust_binary_early.stat.exists | default(false)
- name: Включить weekly aw-db-maintenance timer до Influx проверок
ansible.builtin.systemd:
name: aw-db-maintenance.timer
enabled: true
state: started
daemon_reload: true
when: aw_db_maintenance_rust_binary_early.stat.exists | default(false)
- name: Прочитать текущий aw-server.env для сохранения Influx token
ansible.builtin.slurp:
path: /etc/activitywatch/aw-server.env
register: aw_existing_server_env_raw
failed_when: false
no_log: true
- name: Подготовить effective Influx tokens без вывода секретов
ansible.builtin.set_fact:
aw_existing_server_env_text: "{{ aw_existing_server_env_raw.content | default('') | b64decode }}"
aw_existing_worktime_influx_token: "{{ (aw_existing_server_env_raw.content | default('') | b64decode | regex_search('(?m)^AW_WORKTIME_INFLUX_TOKEN=.*$') | default('', true) | regex_replace('^AW_WORKTIME_INFLUX_TOKEN=', '')) }}"
aw_existing_dlp_influx_token: "{{ (aw_existing_server_env_raw.content | default('') | b64decode | regex_search('(?m)^AW_DLP_INFLUX_TOKEN=.*$') | default('', true) | regex_replace('^AW_DLP_INFLUX_TOKEN=', '')) }}"
no_log: true
- name: Выбрать effective Influx tokens
ansible.builtin.set_fact:
aw_effective_worktime_influx_token: "{{ (aw_worktime_influx_token | default('') | string) if ((aw_worktime_influx_token | default('') | string | length) > 0) else aw_existing_worktime_influx_token }}"
aw_effective_dlp_influx_token: "{{ (aw_dlp_influx_token | default('') | string) if ((aw_dlp_influx_token | default('') | string | length) > 0) else aw_existing_dlp_influx_token }}"
no_log: true
- name: Проверить Influx token для AW worktime exporter
ansible.builtin.assert:
that:
- aw_effective_worktime_influx_token is defined
- aw_effective_worktime_influx_token | length > 0
fail_msg: "aw_worktime_influx_enabled=true, но token пуст и в локальном env, и в текущем /etc/activitywatch/aw-server.env. Exporter будет падать и Grafana не получит worktime-ряды."
when: aw_worktime_influx_enabled | default(false) | bool
- name: Проверить Influx token для AW DLP exporter
ansible.builtin.assert:
that:
- aw_effective_dlp_influx_token is defined
- aw_effective_dlp_influx_token | length > 0
fail_msg: "aw_dlp_influx_enabled=true, но token пуст и в локальном env, и в текущем /etc/activitywatch/aw-server.env. Exporter будет падать и Grafana не получит DLP-ряды."
when: aw_dlp_influx_enabled | default(false) | bool
- name: Проверить destination для AW worktime Influx exporter
ansible.builtin.assert:
that:
- (aw_worktime_influx_url | default('') | string | length) > 0
- "'192.0.2.' not in (aw_worktime_influx_url | default('') | string)"
- "'198.51.100.' not in (aw_worktime_influx_url | default('') | string)"
- "'203.0.113.' not in (aw_worktime_influx_url | default('') | string)"
- (aw_worktime_influx_hosts | default('') | string | length) > 0
- "'HOST-EXAMPLE' not in (aw_worktime_influx_hosts | default('') | string)"
- "'WINDOWS_USER_EXAMPLE' not in (aw_worktime_influx_hosts | default('') | string)"
fail_msg: "aw_worktime_influx_enabled=true, но URL/hosts похожи на public example/TEST-NET значения. Задайте live значения в private inventory/env, не в public repo."
when: aw_worktime_influx_enabled | default(false) | bool
- name: Проверить destination для AW DLP Influx exporter
ansible.builtin.assert:
that:
- (aw_dlp_influx_url | default('') | string | length) > 0
- "'192.0.2.' not in (aw_dlp_influx_url | default('') | string)"
- "'198.51.100.' not in (aw_dlp_influx_url | default('') | string)"
- "'203.0.113.' not in (aw_dlp_influx_url | default('') | string)"
- (aw_dlp_influx_hosts | default('') | string | length) > 0
- "'HOST-EXAMPLE' not in (aw_dlp_influx_hosts | default('') | string)"
- "'WINDOWS_USER_EXAMPLE' not in (aw_dlp_influx_hosts | default('') | string)"
fail_msg: "aw_dlp_influx_enabled=true, но URL/hosts похожи на public example/TEST-NET значения. Задайте live значения в private inventory/env, не в public repo."
when: aw_dlp_influx_enabled | default(false) | bool
- name: Записать /etc/activitywatch/aw-server.env перед хотфиксами
ansible.builtin.copy:
dest: /etc/activitywatch/aw-server.env
mode: "0640"
owner: root
group: root
content: |
AW_SERVER_BIND_HOST={{ aw_server_bind_host }}
AW_SERVER_PORT={{ aw_server_port }}
AW_SERVER_DATA_DIR={{ aw_server_data_dir }}
AW_SERVER_DB_PATH={{ aw_server_db_path }}
AW_SERVER_LOG_DIR={{ aw_server_log_dir }}
AW_SERVER_WEBUI_DIR={{ aw_server_webui_dir }}
AW_SERVER_USER={{ aw_server_user }}
AW_SERVER_GROUP={{ aw_server_group }}
AW_WORKTIME_REPORT_BASE={{ aw_worktime_report_base }}
AW_WORKTIME_TZ={{ aw_worktime_timezone }}
AW_WORKTIME_HOST={{ aw_worktime_host | default(aw_monitored_windows_hostname | default('HOST-EXAMPLE')) }}
AW_DLP_IOC_DIR={{ aw_dlp_ioc_workdir }}/output
AW_DLP_POLICY_ENGINE_BIND_HOST={{ aw_dlp_policy_engine_bind_host }}
AW_DLP_POLICY_ENGINE_PORT={{ aw_dlp_policy_engine_port }}
AW_DLP_POLICY_ENGINE_DB_PATH={{ aw_dlp_policy_engine_db_path }}
AW_DLP_CASE_BIND_HOST={{ aw_dlp_case_bind_host }}
AW_DLP_CASE_PORT={{ aw_dlp_case_port }}
AW_DLP_CASE_DB_PATH={{ aw_dlp_case_db_path }}
AW_DLP_COMPLIANCE_REPORT_DIR={{ aw_dlp_compliance_report_dir }}
AW_DLP_COMPLIANCE_TEMPLATE={{ aw_dlp_compliance_template_path }}
AW_SERVER_URL=http://127.0.0.1:5600
XDG_DATA_HOME={{ aw_server_data_dir }}/.local/share
XDG_CONFIG_HOME={{ aw_server_data_dir }}/.config
AW_WORKTIME_INFLUX_ENABLED={{ 'true' if (aw_worktime_influx_enabled | default(false) | bool) else 'false' }}
AW_WORKTIME_INFLUX_URL={{ aw_worktime_influx_url | default('') }}
AW_WORKTIME_INFLUX_ORG={{ aw_worktime_influx_org | default('proxmox') }}
AW_WORKTIME_INFLUX_BUCKET={{ aw_worktime_influx_bucket | default('aw_metrics') }}
AW_WORKTIME_INFLUX_HOSTS={{ aw_worktime_influx_hosts | default('HOST-EXAMPLE') }}
AW_WORKTIME_INFLUX_DAYS={{ aw_worktime_influx_days | default('today,yesterday') }}
AW_WORKTIME_INFLUX_TOKEN={{ aw_effective_worktime_influx_token | default('') }}
AW_WORKTIME_MANAGEMENT_HISTORY_DIR={{ aw_worktime_management_history_dir | default(aw_server_data_dir ~ '/worktime-management-history') }}
AW_WORKTIME_MANAGEMENT_HISTORY_DAYS={{ aw_worktime_management_history_days | default(31) }}
AW_WORKTIME_MANAGEMENT_HISTORY_RETENTION_DAYS={{ aw_worktime_management_history_retention_days | default(120) }}
AW_WORKTIME_MANAGER_OVERLOAD_COVERAGE_PCT={{ aw_worktime_manager_overload_coverage_pct | default(115) }}
AW_WORKTIME_MANAGER_TREND_MIN_POINTS={{ aw_worktime_manager_trend_min_points | default(3) }}
AW_WORKTIME_MANAGER_TREND_DELTA_PCT={{ aw_worktime_manager_trend_delta_pct | default(10) }}
AW_WORKTIME_MANAGER_OFF_HOURS_THRESHOLD_SECONDS={{ aw_worktime_manager_off_hours_threshold_seconds | default(1800) }}
AW_WORKTIME_MANAGER_INTERPRETATION_POLICY={{ aw_worktime_interpretation_policy_path | default('/etc/activitywatch/worktime-interpretation-policy.json') }}
AW_DLP_INFLUX_ENABLED={{ 'true' if (aw_dlp_influx_enabled | default(false) | bool) else 'false' }}
AW_DLP_INFLUX_URL={{ aw_dlp_influx_url | default('') }}
AW_DLP_INFLUX_ORG={{ aw_dlp_influx_org | default('proxmox') }}
AW_DLP_INFLUX_BUCKET={{ aw_dlp_influx_bucket | default('aw_metrics') }}
AW_DLP_INFLUX_HOSTS={{ aw_dlp_influx_hosts | default('HOST-EXAMPLE') }}
AW_DLP_INFLUX_LOOKBACK_DAYS={{ aw_dlp_influx_lookback_days | default(30) }}
AW_DLP_INFLUX_EVENT_LIMIT={{ aw_dlp_influx_event_limit | default(2000) }}
AW_DLP_INFLUX_TOKEN={{ aw_effective_dlp_influx_token | default('') }}
AW_DLP_AW_API_BASE=http://127.0.0.1:5600/api/0
AW_DLP_CASE_API_BASE=http://127.0.0.1:5602/api/0/dlp/cases
AW_EXPECT_START_OF_DAY={{ aw_worktime_start_of_day | default('') }}
AW_EXPECT_ALWAYS_ACTIVE_PATTERN={{ aw_server_always_active_pattern | default('') }}
AW_EXPECT_LANDINGPAGE={{ aw_server_landingpage | default('') }}
AW_HEALTH_STRICT_FILEOPS={{ aw_health_strict_fileops | default(0) }}
AW_MONITORED_WINDOWS_HOST={{ aw_monitored_windows_host }}
AW_MONITORED_WINDOWS_HOSTNAME={{ aw_monitored_windows_hostname }}
AW_RUS_HEALTH_WORKTIME_API={{ aw_rus_health_worktime_api_base | default('http://127.0.0.1:5610') }}
AW_RUS_HEALTH_STATE_DIR={{ aw_rus_health_state_dir }}
AW_RUS_HEALTH_VALIDATION_DIR={{ aw_rus_health_validation_dir }}
AW_RUS_HEALTH_SESSION_EVENTS_MAX_AGE_SECONDS={{ aw_rus_health_session_events_max_age_seconds | default(86400) }}
AW_RUS_HEALTH_GUARD_MAX_AGE_SECONDS={{ aw_rus_health_guard_max_age_seconds | default(300) }}
AW_RUS_HEALTH_GUARD_REQUIRED={{ 1 if (aw_rus_health_guard_required | default(true) | bool) else 0 }}
AW_RUS_SLO_STATE_DIR={{ aw_server_data_dir }}/slo
AW_RUS_SLO_AW_BASE=http://127.0.0.1:5600
AW_RUS_SLO_WORKTIME_BASE={{ aw_rus_health_worktime_api_base | default('http://127.0.0.1:5610') }}
AW_RUS_SLO_TARGET_PERCENT={{ aw_rus_slo_target_percent | default('99.97') }}
AW_BROWSER_SMOKE_AW_BASE=http://127.0.0.1:5600
AW_BROWSER_SMOKE_WORKTIME_BASE={{ aw_rus_health_worktime_api_base | default('http://127.0.0.1:5610') }}
AW_BROWSER_SMOKE_HOST={{ aw_monitored_windows_hostname }}
AW_BROWSER_SMOKE_OUTPUT_DIR={{ aw_server_data_dir }}/browser-smoke
AW_BROWSER_SMOKE_ENGINE={{ aw_browser_smoke_engine | default('chromium-cli') }}
AW_BROWSER_SMOKE_TIMEOUT_MS={{ aw_browser_smoke_timeout_ms | default(20000) }}
AW_BROWSER_SMOKE_RENDER_TIMEOUT_MS={{ aw_browser_smoke_render_timeout_ms | default(15000) }}
AW_HAYABUSA_AUTO_CASE_ENABLED={{ 'true' if (aw_hayabusa_auto_case_enabled | default(true) | bool) else 'false' }}
AW_HAYABUSA_AUTO_CASE_MIN_SEVERITY={{ aw_hayabusa_auto_case_min_severity | default('medium') }}
AW_HAYABUSA_TELEGRAM_ENABLED={{ 'true' if (aw_hayabusa_telegram_enabled | default(false) | bool) else 'false' }}
AW_HAYABUSA_TELEGRAM_MIN_SEVERITY={{ aw_hayabusa_telegram_min_severity | default('high') }}
AW_HAYABUSA_TELEGRAM_BOT_TOKEN={{ aw_hayabusa_telegram_bot_token | default('') }}
AW_HAYABUSA_TELEGRAM_CHAT_IDS={{ aw_hayabusa_telegram_chat_ids | default('') }}
- name: Создать каталог DLP policy engine
ansible.builtin.file:
path: /opt/activitywatch/dlp-policy-engine
state: directory
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
mode: "0755"
when: aw_dlp_policy_engine_enabled | default(false) | bool
- name: Установить systemd unit DLP policy engine
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/dlp-policy-engine/dlp-policy-engine.service"
dest: /etc/systemd/system/aw-dlp-policy-engine.service
owner: root
group: root
mode: "0644"
when: aw_dlp_policy_engine_enabled | default(false) | bool
- name: Проверить локальный Rust DLP policy engine
ansible.builtin.stat:
path: "{{ aw_rust_release_dir }}/dlp-policy-engine"
delegate_to: localhost
register: aw_dlp_policy_engine_rust_binary
become: false
when: aw_dlp_policy_engine_enabled | default(false) | bool
- name: Требовать Rust DLP policy engine artifact
ansible.builtin.assert:
that:
- aw_dlp_policy_engine_rust_binary.stat.exists | default(false)
fail_msg: "Missing Rust artifact: {{ aw_rust_release_dir }}/dlp-policy-engine"
when: aw_dlp_policy_engine_enabled | default(false) | bool
- name: Установить Rust DLP policy engine
ansible.builtin.copy:
src: "{{ aw_rust_release_dir }}/dlp-policy-engine"
dest: /usr/local/bin/aw-dlp-policy-engine-rust
owner: root
group: root
mode: "0755"
when:
- aw_dlp_policy_engine_enabled | default(false) | bool
- aw_dlp_policy_engine_rust_binary.stat.exists | default(false)
- name: Создать каталог DLP content analysis
ansible.builtin.file:
path: /opt/activitywatch/dlp-content-analysis
state: directory
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
mode: "0755"
when: aw_dlp_content_analysis_enabled | default(true) | bool
- name: Скопировать файлы DLP content analysis
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/dlp-content-analysis/"
dest: /opt/activitywatch/dlp-content-analysis/
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
mode: "0644"
when: aw_dlp_content_analysis_enabled | default(true) | bool
- name: Установить wrapper запуска DLP content analysis через virtualenv
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/dlp-content-analysis/aw-dlp-content-analyzer.sh"
dest: /usr/local/bin/aw-dlp-content-analyzer
owner: root
group: root
mode: "0755"
when: aw_dlp_content_analysis_enabled | default(true) | bool
- name: Проверить локальный Rust DLP content analyzer
ansible.builtin.stat:
path: "{{ aw_rust_release_dir }}/dlp-content-analyzer"
delegate_to: localhost
register: dlp_content_analyzer_rust_binary
become: false
when: aw_dlp_content_analysis_enabled | default(true) | bool
- name: Установить Rust DLP content analyzer
ansible.builtin.copy:
src: "{{ aw_rust_release_dir }}/dlp-content-analyzer"
dest: /usr/local/bin/aw-dlp-content-analyzer-rust
owner: root
group: root
mode: "0755"
when:
- aw_dlp_content_analysis_enabled | default(true) | bool
- dlp_content_analyzer_rust_binary.stat.exists | default(false)
- name: Создать virtualenv DLP content analysis
ansible.builtin.command:
cmd: python3 -m venv /opt/activitywatch/dlp-content-analysis/.venv
args:
creates: /opt/activitywatch/dlp-content-analysis/.venv/bin/python
when: aw_dlp_content_analysis_enabled | default(true) | bool
- name: Установить зависимости DLP content analysis
ansible.builtin.pip:
requirements: /opt/activitywatch/dlp-content-analysis/requirements.txt
virtualenv: /opt/activitywatch/dlp-content-analysis/.venv
when: aw_dlp_content_analysis_enabled | default(true) | bool
- name: Создать каталог DLP integrations
ansible.builtin.file:
path: /opt/activitywatch/dlp-integrations
state: directory
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
mode: "0755"
when: aw_dlp_integrations_enabled | default(true) | bool
- name: Скопировать файлы DLP integrations
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/dlp-integrations/{{ item }}"
dest: "/opt/activitywatch/dlp-integrations/{{ item }}"
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
mode: "0644"
loop:
- cef-config.yaml
- syslog-forwarder-config.yaml
- webhook-config.yaml
when: aw_dlp_integrations_enabled | default(true) | bool
- name: Создать state каталог DLP integrations
ansible.builtin.file:
path: /var/lib/activitywatch/dlp-integrations
state: directory
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
mode: "0755"
when: aw_dlp_integrations_enabled | default(true) | bool
- name: Установить systemd unit CEF exporter
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/dlp-integrations/cef-exporter.service"
dest: /etc/systemd/system/aw-dlp-cef-exporter.service
owner: root
group: root
mode: "0644"
when: aw_dlp_integrations_enabled | default(true) | bool
- name: Установить systemd timer CEF exporter
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/dlp-integrations/cef-exporter.timer"
dest: /etc/systemd/system/aw-dlp-cef-exporter.timer
owner: root
group: root
mode: "0644"
when: aw_dlp_integrations_enabled | default(true) | bool
- name: Проверить локальный Rust CEF exporter
ansible.builtin.stat:
path: "{{ aw_rust_release_dir }}/dlp-cef-exporter"
delegate_to: localhost
register: dlp_cef_exporter_rust_binary
become: false
when: aw_dlp_integrations_enabled | default(true) | bool
- name: Требовать Rust CEF exporter artifact
ansible.builtin.assert:
that:
- dlp_cef_exporter_rust_binary.stat.exists | default(false)
fail_msg: "Missing Rust artifact: {{ aw_rust_release_dir }}/dlp-cef-exporter"
when: aw_dlp_integrations_enabled | default(true) | bool
- name: Установить Rust CEF exporter
ansible.builtin.copy:
src: "{{ aw_rust_release_dir }}/dlp-cef-exporter"
dest: /usr/local/bin/dlp-cef-exporter-rust
owner: root
group: root
mode: "0755"
when:
- aw_dlp_integrations_enabled | default(true) | bool
- dlp_cef_exporter_rust_binary.stat.exists | default(false)
- name: Установить systemd unit syslog forwarder
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/dlp-integrations/syslog-forwarder.service"
dest: /etc/systemd/system/aw-dlp-syslog-forwarder.service
owner: root
group: root
mode: "0644"
when: aw_dlp_integrations_enabled | default(true) | bool
- name: Установить systemd timer syslog forwarder
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/dlp-integrations/syslog-forwarder.timer"
dest: /etc/systemd/system/aw-dlp-syslog-forwarder.timer
owner: root
group: root
mode: "0644"
when: aw_dlp_integrations_enabled | default(true) | bool
- name: Проверить локальный Rust syslog forwarder
ansible.builtin.stat:
path: "{{ aw_rust_release_dir }}/dlp-syslog-forwarder"
delegate_to: localhost
register: dlp_syslog_forwarder_rust_binary
become: false
when: aw_dlp_integrations_enabled | default(true) | bool
- name: Требовать Rust syslog forwarder artifact
ansible.builtin.assert:
that:
- dlp_syslog_forwarder_rust_binary.stat.exists | default(false)
fail_msg: "Missing Rust artifact: {{ aw_rust_release_dir }}/dlp-syslog-forwarder"
when: aw_dlp_integrations_enabled | default(true) | bool
- name: Установить Rust syslog forwarder
ansible.builtin.copy:
src: "{{ aw_rust_release_dir }}/dlp-syslog-forwarder"
dest: /usr/local/bin/dlp-syslog-forwarder-rust
owner: root
group: root
mode: "0755"
when:
- aw_dlp_integrations_enabled | default(true) | bool
- dlp_syslog_forwarder_rust_binary.stat.exists | default(false)
- name: Установить systemd unit webhook sender
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/dlp-integrations/webhook-sender.service"
dest: /etc/systemd/system/aw-dlp-webhook-sender.service
owner: root
group: root
mode: "0644"
when: aw_dlp_integrations_enabled | default(true) | bool
- name: Установить systemd timer webhook sender
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/dlp-integrations/webhook-sender.timer"
dest: /etc/systemd/system/aw-dlp-webhook-sender.timer
owner: root
group: root
mode: "0644"
when: aw_dlp_integrations_enabled | default(true) | bool
- name: Проверить локальный Rust webhook sender
ansible.builtin.stat:
path: "{{ aw_rust_release_dir }}/dlp-webhook-sender"
delegate_to: localhost
register: dlp_webhook_sender_rust_binary
become: false
when: aw_dlp_integrations_enabled | default(true) | bool
- name: Требовать Rust webhook sender artifact
ansible.builtin.assert:
that:
- dlp_webhook_sender_rust_binary.stat.exists | default(false)
fail_msg: "Missing Rust artifact: {{ aw_rust_release_dir }}/dlp-webhook-sender"
when: aw_dlp_integrations_enabled | default(true) | bool
- name: Установить Rust webhook sender
ansible.builtin.copy:
src: "{{ aw_rust_release_dir }}/dlp-webhook-sender"
dest: /usr/local/bin/dlp-webhook-sender-rust
owner: root
group: root
mode: "0755"
when:
- aw_dlp_integrations_enabled | default(true) | bool
- dlp_webhook_sender_rust_binary.stat.exists | default(false)
- name: Создать каталог DLP case management
ansible.builtin.file:
path: /opt/activitywatch/dlp-case-management
state: directory
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
mode: "0755"
when: aw_dlp_case_management_enabled | default(true) | bool
- name: Установить systemd unit DLP case management
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/dlp-case-management/case-service.service"
dest: /etc/systemd/system/aw-dlp-case-management.service
owner: root
group: root
mode: "0644"
when: aw_dlp_case_management_enabled | default(true) | bool
- name: Проверить локальный Rust DLP case management
ansible.builtin.stat:
path: "{{ aw_rust_release_dir }}/dlp-case-management"
delegate_to: localhost
register: aw_dlp_case_management_rust_binary
become: false
when: aw_dlp_case_management_enabled | default(true) | bool
- name: Требовать Rust DLP case management artifact
ansible.builtin.assert:
that:
- aw_dlp_case_management_rust_binary.stat.exists | default(false)
fail_msg: "Missing Rust artifact: {{ aw_rust_release_dir }}/dlp-case-management"
when: aw_dlp_case_management_enabled | default(true) | bool
- name: Установить Rust DLP case management
ansible.builtin.copy:
src: "{{ aw_rust_release_dir }}/dlp-case-management"
dest: /usr/local/bin/aw-dlp-case-management-rust
owner: root
group: root
mode: "0755"
when:
- aw_dlp_case_management_enabled | default(true) | bool
- aw_dlp_case_management_rust_binary.stat.exists | default(false)
- name: Создать каталоги DLP compliance
ansible.builtin.file:
path: "{{ item }}"
state: directory
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
mode: "0755"
loop:
- /opt/activitywatch/dlp-compliance
- /opt/activitywatch/dlp-compliance/templates
- "{{ aw_dlp_compliance_report_dir }}"
when: aw_dlp_compliance_enabled | default(true) | bool
- name: Скопировать файлы DLP compliance
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/dlp-compliance/{{ item.src }}"
dest: "{{ item.dest }}"
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
mode: "{{ item.mode }}"
loop:
- { src: "templates/152-fz-report.html", dest: "/opt/activitywatch/dlp-compliance/templates/152-fz-report.html", mode: "0644" }
- { src: "templates/pci-dss-report.html", dest: "/opt/activitywatch/dlp-compliance/templates/pci-dss-report.html", mode: "0644" }
- { src: "report-scheduler.service", dest: "/etc/systemd/system/aw-dlp-report-scheduler.service", mode: "0644" }
- { src: "report-scheduler.timer", dest: "/etc/systemd/system/aw-dlp-report-scheduler.timer", mode: "0644" }
when: aw_dlp_compliance_enabled | default(true) | bool
- name: Проверить локальный Rust DLP compliance
ansible.builtin.stat:
path: "{{ aw_rust_release_dir }}/dlp-compliance"
delegate_to: localhost
register: aw_dlp_compliance_rust_binary
become: false
when: aw_dlp_compliance_enabled | default(true) | bool
- name: Требовать Rust DLP compliance artifact
ansible.builtin.assert:
that:
- aw_dlp_compliance_rust_binary.stat.exists | default(false)
fail_msg: "Missing Rust artifact: {{ aw_rust_release_dir }}/dlp-compliance"
when: aw_dlp_compliance_enabled | default(true) | bool
- name: Установить Rust DLP compliance
ansible.builtin.copy:
src: "{{ aw_rust_release_dir }}/dlp-compliance"
dest: /usr/local/bin/aw-dlp-compliance-rust
owner: root
group: root
mode: "0755"
when:
- aw_dlp_compliance_enabled | default(true) | bool
- aw_dlp_compliance_rust_binary.stat.exists | default(false)
- name: Проверить локальный Rust dlp-admin-cli
ansible.builtin.stat:
path: "{{ aw_rust_release_dir }}/dlp-admin-cli"
delegate_to: localhost
register: aw_dlp_admin_cli_rust_binary
- name: Требовать Rust dlp-admin-cli artifact
ansible.builtin.assert:
that:
- aw_dlp_admin_cli_rust_binary.stat.exists | default(false)
fail_msg: "Missing Rust artifact: {{ aw_rust_release_dir }}/dlp-admin-cli"
- name: Установить Rust dlp-admin-cli
ansible.builtin.copy:
src: "{{ aw_rust_release_dir }}/dlp-admin-cli"
dest: /usr/local/bin/dlp-admin-cli
owner: root
group: root
mode: "0755"
when: aw_dlp_admin_cli_rust_binary.stat.exists
- name: Создать каталог daily history для AW worktime management
ansible.builtin.file:
path: "{{ aw_worktime_management_history_dir | default(aw_server_data_dir ~ '/worktime-management-history') }}"
state: directory
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
mode: "0750"
- name: Установить initial policy интерпретации Workforce если отсутствует
ansible.builtin.copy:
dest: "{{ aw_worktime_interpretation_policy_path | default('/etc/activitywatch/worktime-interpretation-policy.json') }}"
owner: root
group: root
mode: "0644"
force: false
content: "{{ lookup('file', aw_repo_root + '/configs/worktime-interpretation-policy.example.json') }}"
- name: Проверить локальный Rust AW worktime API
ansible.builtin.stat:
path: "{{ aw_rust_release_dir }}/worktime-api"
delegate_to: localhost
register: aw_worktime_api_rust_binary
become: false
- name: Требовать Rust AW worktime API artifact
ansible.builtin.assert:
that:
- aw_worktime_api_rust_binary.stat.exists | default(false)
fail_msg: "Missing Rust artifact: {{ aw_rust_release_dir }}/worktime-api"
- name: Установить Rust AW worktime API
ansible.builtin.copy:
src: "{{ aw_rust_release_dir }}/worktime-api"
dest: /usr/local/bin/aw-worktime-api-rust
owner: root
group: root
mode: "0755"
when: aw_worktime_api_rust_binary.stat.exists | default(false)
- name: Установить systemd unit AW worktime API
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/aw-worktime-api.service"
dest: /etc/systemd/system/aw-worktime-api.service
owner: root
group: root
mode: "0644"
- name: Проверить локальный Rust AW worktime UI bridge
ansible.builtin.stat:
path: "{{ aw_rust_release_dir }}/worktime-ui-bridge"
delegate_to: localhost
register: aw_worktime_ui_bridge_rust_binary
become: false
- name: Требовать Rust AW worktime UI bridge artifact
ansible.builtin.assert:
that:
- aw_worktime_ui_bridge_rust_binary.stat.exists | default(false)
fail_msg: "Missing Rust artifact: {{ aw_rust_release_dir }}/worktime-ui-bridge"
- name: Установить Rust AW worktime UI bridge
ansible.builtin.copy:
src: "{{ aw_rust_release_dir }}/worktime-ui-bridge"
dest: /usr/local/bin/aw-worktime-ui-bridge-rust
owner: root
group: root
mode: "0755"
when: aw_worktime_ui_bridge_rust_binary.stat.exists | default(false)
- name: Проверить локальный Rust AW worktime autoheal
ansible.builtin.stat:
path: "{{ aw_rust_release_dir }}/worktime-autoheal"
delegate_to: localhost
register: aw_worktime_autoheal_rust_binary
become: false
- name: Требовать Rust AW worktime autoheal artifact
ansible.builtin.assert:
that:
- aw_worktime_autoheal_rust_binary.stat.exists | default(false)
fail_msg: "Missing Rust artifact: {{ aw_rust_release_dir }}/worktime-autoheal"
- name: Установить Rust AW worktime autoheal
ansible.builtin.copy:
src: "{{ aw_rust_release_dir }}/worktime-autoheal"
dest: /usr/local/bin/aw-worktime-autoheal-rust
owner: root
group: root
mode: "0755"
when: aw_worktime_autoheal_rust_binary.stat.exists | default(false)
- name: Проверить локальный Rust AW worktime prewarm
ansible.builtin.stat:
path: "{{ aw_rust_release_dir }}/worktime-prewarm"
delegate_to: localhost
register: aw_worktime_prewarm_rust_binary
become: false
- name: Требовать Rust AW worktime prewarm artifact
ansible.builtin.assert:
that:
- aw_worktime_prewarm_rust_binary.stat.exists | default(false)
fail_msg: "Missing Rust artifact: {{ aw_rust_release_dir }}/worktime-prewarm"
- name: Установить Rust AW worktime prewarm
ansible.builtin.copy:
src: "{{ aw_rust_release_dir }}/worktime-prewarm"
dest: /usr/local/bin/aw-worktime-prewarm-rust
owner: root
group: root
mode: "0755"
when: aw_worktime_prewarm_rust_binary.stat.exists | default(false)
- name: Создать server-side ops bundle для AW ops helpers
ansible.builtin.file:
path: /opt/activitywatch/aw-rus-ops
state: directory
owner: root
group: root
mode: "0755"
- name: Установить скрипт aw-health-check
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/aw-health-check-wrapper.sh"
dest: /usr/local/bin/aw-health-check
owner: root
group: root
mode: "0755"
- name: Проверить локальный Rust aw-health-check
ansible.builtin.stat:
path: "{{ aw_rust_release_dir }}/aw-health-check"
delegate_to: localhost
register: aw_health_check_rust_binary
become: false
- name: Установить Rust aw-health-check
ansible.builtin.copy:
src: "{{ aw_rust_release_dir }}/aw-health-check"
dest: /usr/local/bin/aw-health-check-rust
owner: root
group: root
mode: "0755"
when: aw_health_check_rust_binary.stat.exists | default(false)
- name: Требовать Rust aw-health-check artifact
ansible.builtin.assert:
that:
- aw_health_check_rust_binary.stat.exists | default(false)
fail_msg: "Rust aw-health-check artifact is required at {{ aw_rust_release_dir }}/aw-health-check"
- name: Проверить локальный Rust aw-db-health
ansible.builtin.stat:
path: "{{ aw_rust_release_dir }}/aw-db-health"
delegate_to: localhost
register: aw_db_health_rust_binary
become: false
- name: Установить Rust aw-db-health
ansible.builtin.copy:
src: "{{ aw_rust_release_dir }}/aw-db-health"
dest: /usr/local/bin/aw-db-health
owner: root
group: root
mode: "0755"
when: aw_db_health_rust_binary.stat.exists | default(false)
- name: Установить скрипт check-aw-data
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/check-aw-data-wrapper.sh"
dest: /usr/local/bin/check-aw-data
owner: root
group: root
mode: "0755"
- name: Положить legacy check-aw-data в server-side ops bundle
ansible.builtin.copy:
src: "{{ aw_repo_root }}/scripts/legacy/check-aw-data.sh"
dest: /opt/activitywatch/aw-rus-ops/check-aw-data.sh
owner: root
group: root
mode: "0755"
- name: Проверить локальный Rust check-aw-data
ansible.builtin.stat:
path: "{{ aw_rust_release_dir }}/check-aw-data"
delegate_to: localhost
register: check_aw_data_rust_binary
become: false
- name: Установить Rust check-aw-data
ansible.builtin.copy:
src: "{{ aw_rust_release_dir }}/check-aw-data"
dest: /usr/local/bin/check-aw-data-rust
owner: root
group: root
mode: "0755"
when: check_aw_data_rust_binary.stat.exists | default(false)
- name: Проверить локальный Rust dlp-health-check
ansible.builtin.stat:
path: "{{ aw_rust_release_dir }}/dlp-health-check"
delegate_to: localhost
register: dlp_health_check_rust_binary
become: false
- name: Установить Rust dlp-health-check
ansible.builtin.copy:
src: "{{ aw_rust_release_dir }}/dlp-health-check"
dest: /usr/local/bin/dlp-health-check
owner: root
group: root
mode: "0755"
when: dlp_health_check_rust_binary.stat.exists | default(false)
- name: Проверить локальный Rust AW-RUS healthd
ansible.builtin.stat:
path: "{{ aw_rust_release_dir }}/aw-rus-healthd"
delegate_to: localhost
register: aw_rus_healthd_rust_binary
become: false
- name: Проверить локальный Rust AW-RUS SLO monitor
ansible.builtin.stat:
path: "{{ aw_rust_release_dir }}/aw-slo-monitor"
delegate_to: localhost
register: aw_slo_monitor_rust_binary
become: false
- name: Требовать Rust dlp-health-check artifact
ansible.builtin.assert:
that:
- dlp_health_check_rust_binary.stat.exists | default(false)
fail_msg: "Missing Rust artifact: {{ aw_rust_release_dir }}/dlp-health-check"
- name: Требовать Rust AW-RUS healthd artifact
ansible.builtin.assert:
that:
- aw_rus_healthd_rust_binary.stat.exists | default(false)
fail_msg: "Missing Rust artifact: {{ aw_rust_release_dir }}/aw-rus-healthd"
- name: Требовать Rust AW-RUS SLO monitor artifact
ansible.builtin.assert:
that:
- aw_slo_monitor_rust_binary.stat.exists | default(false)
fail_msg: "Missing Rust artifact: {{ aw_rust_release_dir }}/aw-slo-monitor"
- name: Установить Rust AW-RUS healthd
ansible.builtin.copy:
src: "{{ aw_rust_release_dir }}/aw-rus-healthd"
dest: /usr/local/bin/aw-rus-healthd-rust
owner: root
group: root
mode: "0755"
- name: Установить Rust AW-RUS SLO monitor
ansible.builtin.copy:
src: "{{ aw_rust_release_dir }}/aw-slo-monitor"
dest: /usr/local/bin/aw-slo-monitor-rust
owner: root
group: root
mode: "0755"
when: aw_slo_monitor_rust_binary.stat.exists | default(false)
- name: Установить browser smoke скрипт
ansible.builtin.copy:
src: "{{ aw_repo_root }}/scripts/aw-webui-browser-smoke.mjs"
dest: /usr/local/lib/aw-rus-browser-smoke/aw-webui-browser-smoke.mjs
owner: root
group: root
mode: "0755"
when: aw_browser_smoke_enabled | default(true) | bool
- name: Установить systemd unit AW worktime UI bridge
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/aw-worktime-ui-bridge.service"
dest: /etc/systemd/system/aw-worktime-ui-bridge.service
owner: root
group: root
mode: "0644"
- name: Установить systemd timer AW worktime UI bridge
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/aw-worktime-ui-bridge.timer"
dest: /etc/systemd/system/aw-worktime-ui-bridge.timer
owner: root
group: root
mode: "0644"
- name: Установить systemd unit AW worktime autoheal
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/aw-worktime-autoheal.service"
dest: /etc/systemd/system/aw-worktime-autoheal.service
owner: root
group: root
mode: "0644"
- name: Установить systemd timer AW worktime autoheal
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/aw-worktime-autoheal.timer"
dest: /etc/systemd/system/aw-worktime-autoheal.timer
owner: root
group: root
mode: "0644"
- name: Установить systemd unit AW worktime prewarm
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/aw-worktime-prewarm.service"
dest: /etc/systemd/system/aw-worktime-prewarm.service
owner: root
group: root
mode: "0644"
- name: Установить systemd timer AW worktime prewarm
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/aw-worktime-prewarm.timer"
dest: /etc/systemd/system/aw-worktime-prewarm.timer
owner: root
group: root
mode: "0644"
- name: Установить systemd unit AW-RUS healthd
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/aw-rus-healthd.service"
dest: /etc/systemd/system/aw-rus-healthd.service
owner: root
group: root
mode: "0644"
- name: Установить systemd timer AW-RUS healthd
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/aw-rus-healthd.timer"
dest: /etc/systemd/system/aw-rus-healthd.timer
owner: root
group: root
mode: "0644"
- name: Установить systemd unit AW-RUS SLO monitor
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/aw-slo-monitor.service"
dest: /etc/systemd/system/aw-slo-monitor.service
owner: root
group: root
mode: "0644"
- name: Установить systemd timer AW-RUS SLO monitor
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/aw-slo-monitor.timer"
dest: /etc/systemd/system/aw-slo-monitor.timer
owner: root
group: root
mode: "0644"
- name: Установить systemd unit AW-RUS browser smoke
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/aw-browser-smoke.service"
dest: /etc/systemd/system/aw-browser-smoke.service
owner: root
group: root
mode: "0644"
when: aw_browser_smoke_enabled | default(true) | bool
- name: Установить systemd timer AW-RUS browser smoke
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/aw-browser-smoke.timer"
dest: /etc/systemd/system/aw-browser-smoke.timer
owner: root
group: root
mode: "0644"
when: aw_browser_smoke_enabled | default(true) | bool
- name: Установить systemd unit AW worktime Influx exporter
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/aw-worktime-influx-exporter.service"
dest: /etc/systemd/system/aw-worktime-influx-exporter.service
owner: root
group: root
mode: "0644"
when: aw_worktime_influx_enabled | default(false) | bool
- name: Проверить локальный Rust AW worktime Influx exporter
ansible.builtin.stat:
path: "{{ aw_rust_release_dir }}/worktime-influx-exporter"
delegate_to: localhost
register: aw_worktime_influx_exporter_rust_binary
become: false
when: aw_worktime_influx_enabled | default(false) | bool
- name: Требовать Rust AW worktime Influx exporter artifact
ansible.builtin.assert:
that:
- aw_worktime_influx_exporter_rust_binary.stat.exists | default(false)
fail_msg: "Missing Rust artifact: {{ aw_rust_release_dir }}/worktime-influx-exporter"
when: aw_worktime_influx_enabled | default(false) | bool
- name: Установить Rust AW worktime Influx exporter
ansible.builtin.copy:
src: "{{ aw_rust_release_dir }}/worktime-influx-exporter"
dest: /usr/local/bin/aw-worktime-influx-exporter-rust
owner: root
group: root
mode: "0755"
when:
- aw_worktime_influx_enabled | default(false) | bool
- aw_worktime_influx_exporter_rust_binary.stat.exists | default(false)
- name: Установить systemd timer AW worktime Influx exporter
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/aw-worktime-influx-exporter.timer"
dest: /etc/systemd/system/aw-worktime-influx-exporter.timer
owner: root
group: root
mode: "0644"
when: aw_worktime_influx_enabled | default(false) | bool
- name: Установить systemd unit AW DLP Influx exporter
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/aw-dlp-influx-exporter.service"
dest: /etc/systemd/system/aw-dlp-influx-exporter.service
owner: root
group: root
mode: "0644"
when: aw_dlp_influx_enabled | default(false) | bool
- name: Проверить локальный Rust AW DLP Influx exporter
ansible.builtin.stat:
path: "{{ aw_rust_release_dir }}/dlp-influx-exporter"
delegate_to: localhost
register: aw_dlp_influx_exporter_rust_binary
become: false
when: aw_dlp_influx_enabled | default(false) | bool
- name: Требовать Rust AW DLP Influx exporter artifact
ansible.builtin.assert:
that:
- aw_dlp_influx_exporter_rust_binary.stat.exists | default(false)
fail_msg: "Missing Rust artifact: {{ aw_rust_release_dir }}/dlp-influx-exporter"
when: aw_dlp_influx_enabled | default(false) | bool
- name: Установить Rust AW DLP Influx exporter
ansible.builtin.copy:
src: "{{ aw_rust_release_dir }}/dlp-influx-exporter"
dest: /usr/local/bin/aw-dlp-influx-exporter-rust
owner: root
group: root
mode: "0755"
when:
- aw_dlp_influx_enabled | default(false) | bool
- aw_dlp_influx_exporter_rust_binary.stat.exists | default(false)
- name: Установить systemd timer AW DLP Influx exporter
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/aw-dlp-influx-exporter.timer"
dest: /etc/systemd/system/aw-dlp-influx-exporter.timer
owner: root
group: root
mode: "0644"
when: aw_dlp_influx_enabled | default(false) | bool
- name: Перезагрузить systemd после установки AW worktime API
ansible.builtin.systemd:
daemon_reload: true
- name: Включить таймер AW-RUS healthd
ansible.builtin.systemd:
name: aw-rus-healthd.timer
enabled: true
state: started
- name: Включить таймер AW-RUS SLO monitor
ansible.builtin.systemd:
name: aw-slo-monitor.timer
enabled: true
state: started
- name: Включить таймер AW-RUS browser smoke
ansible.builtin.systemd:
name: aw-browser-smoke.timer
enabled: true
state: started
when: aw_browser_smoke_enabled | default(true) | bool
- name: Включить и перезапустить DLP policy engine
ansible.builtin.systemd:
name: aw-dlp-policy-engine.service
enabled: true
state: restarted
when: aw_dlp_policy_engine_enabled | default(false) | bool
- name: Включить и перезапустить timer CEF exporter
ansible.builtin.systemd:
name: aw-dlp-cef-exporter.timer
enabled: true
state: restarted
when: aw_dlp_integrations_enabled | default(true) | bool
- name: Включить и перезапустить timer syslog forwarder
ansible.builtin.systemd:
name: aw-dlp-syslog-forwarder.timer
enabled: true
state: restarted
when: aw_dlp_integrations_enabled | default(true) | bool
- name: Включить и перезапустить timer webhook sender
ansible.builtin.systemd:
name: aw-dlp-webhook-sender.timer
enabled: true
state: restarted
when: aw_dlp_integrations_enabled | default(true) | bool
- name: Включить и перезапустить DLP case management
ansible.builtin.systemd:
name: aw-dlp-case-management.service
enabled: true
state: restarted
when: aw_dlp_case_management_enabled | default(true) | bool
- name: Включить и перезапустить timer DLP compliance report
ansible.builtin.systemd:
name: aw-dlp-report-scheduler.timer
enabled: true
state: restarted
when: aw_dlp_compliance_enabled | default(true) | bool
- name: Выполнить разовый прогон DLP compliance report
ansible.builtin.systemd:
name: aw-dlp-report-scheduler.service
state: started
failed_when: false
when: aw_dlp_compliance_enabled | default(true) | bool
- name: Включить и перезапустить AW worktime API
ansible.builtin.systemd:
name: aw-worktime-api.service
enabled: true
state: restarted
- name: Отключить legacy timer aw-worktime-afk-bridge (если есть)
ansible.builtin.systemd:
name: aw-worktime-afk-bridge.timer
enabled: false
state: stopped
failed_when: false
- name: Включить и перезапустить AW worktime UI bridge timer
ansible.builtin.systemd:
name: aw-worktime-ui-bridge.timer
enabled: true
state: restarted
- name: Выполнить разовый прогон AW worktime UI bridge
ansible.builtin.systemd:
name: aw-worktime-ui-bridge.service
state: started
failed_when: false
- name: Включить и перезапустить AW worktime autoheal timer
ansible.builtin.systemd:
name: aw-worktime-autoheal.timer
enabled: true
state: restarted
- name: Выполнить разовый прогон AW worktime autoheal
ansible.builtin.systemd:
name: aw-worktime-autoheal.service
state: started
failed_when: false
- name: Включить и перезапустить AW worktime prewarm timer
ansible.builtin.systemd:
name: aw-worktime-prewarm.timer
enabled: true
state: restarted
- name: Выполнить разовый прогон AW worktime prewarm
ansible.builtin.systemd:
name: aw-worktime-prewarm.service
state: started
failed_when: false
- name: Включить и перезапустить AW worktime Influx exporter timer
ansible.builtin.systemd:
name: aw-worktime-influx-exporter.timer
enabled: true
state: restarted
when: aw_worktime_influx_enabled | default(false) | bool
- name: Выполнить разовый прогон AW worktime Influx exporter
ansible.builtin.systemd:
name: aw-worktime-influx-exporter.service
state: started
when: aw_worktime_influx_enabled | default(false) | bool
- name: Включить и перезапустить AW DLP Influx exporter timer
ansible.builtin.systemd:
name: aw-dlp-influx-exporter.timer
enabled: true
state: restarted
when: aw_dlp_influx_enabled | default(false) | bool
- name: Выполнить разовый прогон AW DLP Influx exporter
ansible.builtin.systemd:
name: aw-dlp-influx-exporter.service
state: started
when: aw_dlp_influx_enabled | default(false) | bool
- name: Применить хотфиксы compiled JS чанков (Trends, Timespiral, Category helper)
ansible.builtin.command:
cmd: "/opt/activitywatch/aw-server/apply_webui_ru_patch.sh"
register: apply_ru_patch_result
failed_when: false
- name: Вывести результат применения хотфиксов
ansible.builtin.debug:
msg: "apply_webui_ru_patch.sh: {{ apply_ru_patch_result.stdout }}"
- name: Проверить наличие index.html после копирования
ansible.builtin.stat:
path: "{{ aw_server_webui_dir }}/index.html"
register: aw_webui_ru_index
- name: Проверить, что index.html доступен для RU patch
ansible.builtin.assert:
that:
- aw_webui_ru_index.stat.exists
- (aw_webui_ru_index.stat.size | default(0) | int) > 0
fail_msg: "Не найден index.html WebUI для применения RU patch."
- name: Проверить, что index.html не опустел после применения RU patch
ansible.builtin.stat:
path: "{{ aw_server_webui_dir }}/index.html"
register: aw_webui_ru_index_after_patch
- name: Подтвердить, что index.html остался непустым
ansible.builtin.assert:
that:
- aw_webui_ru_index_after_patch.stat.exists
- (aw_webui_ru_index_after_patch.stat.size | default(0) | int) > 0
fail_msg: "index.html WebUI пуст после RU patch."
- name: Удалить старые теги RU patch из index.html
ansible.builtin.replace:
path: "{{ aw_server_webui_dir }}/index.html"
regexp: '<script[^>]+(?:ru-patch-v5\.js|sw-cleanup\.js|aw-ru-patch\.js|aw-sw-cleanup\.js)[^>]*></script>'
replace: ''
- name: Добавить cleanup script RU patch в index.html
ansible.builtin.replace:
path: "{{ aw_server_webui_dir }}/index.html"
regexp: '</head>'
replace: '<script src="/js/sw-cleanup.js?v={{ aw_sw_cleanup_cache_bust }}"></script></head>'
- name: Добавить загрузчик RU patch перед закрытием body
ansible.builtin.replace:
path: "{{ aw_server_webui_dir }}/index.html"
regexp: '</body>'
replace: '<script defer="defer" src="/js/ru-patch-v5.js?v={{ aw_ru_patch_cache_bust }}"></script></body>'
- name: Check Rust merge AW DB binary artifact
ansible.builtin.stat:
path: "{{ aw_rust_release_dir }}/merge-aw-server-dbs"
register: aw_merge_db_rust_binary
delegate_to: localhost
become: false
- name: Требовать Rust merge AW DB artifact
ansible.builtin.assert:
that:
- aw_merge_db_rust_binary.stat.exists | default(false)
fail_msg: "Missing Rust artifact: {{ aw_rust_release_dir }}/merge-aw-server-dbs"
when: aw_legacy_db_merge_enabled | default(false) | bool
- name: Install Rust merge AW DB binary
ansible.builtin.copy:
src: "{{ aw_rust_release_dir }}/merge-aw-server-dbs"
dest: /usr/local/bin/merge-aw-server-dbs
owner: root
group: root
mode: "0755"
when: aw_merge_db_rust_binary.stat.exists | default(false)
- name: Проверить наличие legacy root DB
ansible.builtin.stat:
path: /var/lib/activitywatch/aw-server-rust/sqlite.db
register: aw_legacy_root_db
- name: Проверить наличие target DB
ansible.builtin.stat:
path: "{{ aw_server_db_path }}"
register: aw_target_db
- name: Остановить сервис перед merge server DB
ansible.builtin.systemd:
name: activitywatch-server.service
state: stopped
when:
- aw_legacy_db_merge_enabled | default(false) | bool
- aw_legacy_root_db.stat.exists | default(false)
- name: Создать backup каталоги server DB
ansible.builtin.file:
path: "{{ aw_server_data_dir }}/backups/db"
state: directory
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
mode: "0755"
when:
- aw_legacy_db_merge_enabled | default(false) | bool
- aw_legacy_root_db.stat.exists | default(false)
- name: Backup target DB перед merge
ansible.builtin.copy:
remote_src: true
src: "{{ aw_server_db_path }}"
dest: "{{ aw_server_data_dir }}/backups/db/target-before-merge-{{ ansible_date_time.iso8601_basic_short }}.sqlite.db"
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
mode: "0644"
when:
- aw_legacy_db_merge_enabled | default(false) | bool
- aw_legacy_root_db.stat.exists | default(false)
- aw_target_db.stat.exists | default(false)
- name: Backup legacy root DB перед merge
ansible.builtin.copy:
remote_src: true
src: /var/lib/activitywatch/aw-server-rust/sqlite.db
dest: "{{ aw_server_data_dir }}/backups/db/legacy-root-{{ ansible_date_time.iso8601_basic_short }}.sqlite.db"
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
mode: "0644"
when:
- aw_legacy_db_merge_enabled | default(false) | bool
- aw_legacy_root_db.stat.exists | default(false)
- name: Merge legacy root DB в target DB
ansible.builtin.command:
argv:
- /usr/local/bin/merge-aw-server-dbs
- --base
- /var/lib/activitywatch/aw-server-rust/sqlite.db
- --overlay
- "{{ aw_server_db_path }}"
- --output
- "{{ aw_server_db_path }}.merged"
register: aw_merge_result
failed_when: false
when:
- aw_legacy_db_merge_enabled | default(false) | bool
- aw_legacy_root_db.stat.exists | default(false)
- aw_target_db.stat.exists | default(false)
- name: Показать результат merge legacy root DB
ansible.builtin.debug:
msg: "{{ aw_merge_result.stdout | default(aw_merge_result.stderr | default('merge not executed')) }}"
when:
- aw_legacy_db_merge_enabled | default(false) | bool
- aw_legacy_root_db.stat.exists | default(false)
- aw_target_db.stat.exists | default(false)
- name: Install merged DB as active target DB
ansible.builtin.copy:
remote_src: true
src: "{{ aw_server_db_path }}.merged"
dest: "{{ aw_server_db_path }}"
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
mode: "0644"
when:
- aw_legacy_db_merge_enabled | default(false) | bool
- aw_legacy_root_db.stat.exists | default(false)
- aw_target_db.stat.exists | default(false)
- aw_merge_result is defined
- (aw_merge_result.rc | default(1) | int) == 0
- name: Скопировать legacy root DB в target DB если target ещё не существует
ansible.builtin.copy:
remote_src: true
src: /var/lib/activitywatch/aw-server-rust/sqlite.db
dest: "{{ aw_server_db_path }}"
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
mode: "0644"
when:
- aw_legacy_db_merge_enabled | default(false) | bool
- aw_legacy_root_db.stat.exists | default(false)
- not (aw_target_db.stat.exists | default(false))
- name: Записать aw-server-rust config.toml с разрешёнными CORS origin
ansible.builtin.copy:
dest: "{{ aw_server_data_dir }}/.config/activitywatch/aw-server-rust/config.toml"
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
mode: "0644"
content: |
cors = [
{% for origin in aw_server_cors_origins | default([]) %}
"{{ origin }}"{% if not loop.last %},{% endif %}
{% endfor %}
]
- name: Включить и запустить сервис
ansible.builtin.systemd:
name: activitywatch-server.service
enabled: true
state: restarted
daemon_reload: true
- name: Дождаться ответа API
ansible.builtin.uri:
url: "http://127.0.0.1:{{ aw_server_port }}/api/0/info"
method: GET
status_code: 200
register: aw_api
retries: 10
delay: 3
until: aw_api.status == 200
- name: Считать текущие server-side settings
ansible.builtin.uri:
url: "http://127.0.0.1:{{ aw_server_port }}/api/0/settings/"
method: GET
status_code: 200
register: aw_settings_current
when: aw_apply_worktime_settings | default(false) | bool
- name: Считать текущие server-side views
ansible.builtin.uri:
url: "http://127.0.0.1:{{ aw_server_port }}/api/0/settings/views"
method: GET
status_code: 200
register: aw_views_current
when: aw_apply_worktime_settings | default(false) | bool
- name: Считать текущие server-side classes
ansible.builtin.uri:
url: "http://127.0.0.1:{{ aw_server_port }}/api/0/settings/classes"
method: GET
status_code: 200
register: aw_classes_current
when: aw_apply_worktime_settings | default(false) | bool
- name: Создать backup текущих server-side settings/views/classes
ansible.builtin.copy:
dest: "{{ aw_server_data_dir }}/backups/{{ item.name }}-{{ ansible_date_time.iso8601_basic_short }}.json"
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
mode: "0644"
content: "{{ item.payload | to_nice_json }}"
loop:
- name: settings
payload: "{{ aw_settings_current.json | default({}) }}"
- name: views
payload: "{{ aw_views_current.json | default(none) }}"
- name: classes
payload: "{{ aw_classes_current.json | default(none) }}"
when: aw_apply_worktime_settings | default(false) | bool
- name: Настроить DLP Aggregator (Phase 2)
block:
- name: Создать каталог для скриптов
ansible.builtin.file:
path: "/opt/activitywatch/scripts"
state: directory
owner: root
group: root
mode: "0755"
- name: Проверить локальный Rust DLP aggregator
ansible.builtin.stat:
path: "{{ aw_rust_release_dir }}/dlp-aggregator"
delegate_to: localhost
register: dlp_aggregator_rust_binary
become: false
- name: Требовать Rust DLP aggregator artifact
ansible.builtin.assert:
that:
- dlp_aggregator_rust_binary.stat.exists | default(false)
fail_msg: "Missing Rust artifact: {{ aw_rust_release_dir }}/dlp-aggregator"
- name: Установить Rust DLP aggregator
ansible.builtin.copy:
src: "{{ aw_rust_release_dir }}/dlp-aggregator"
dest: /usr/local/bin/dlp-aggregator-rust
owner: root
group: root
mode: "0755"
when: dlp_aggregator_rust_binary.stat.exists | default(false)
- name: Установить systemd unit для агрегатора
ansible.builtin.copy:
dest: /etc/systemd/system/activitywatch-dlp-aggregator.service
owner: root
group: root
mode: "0644"
content: |
[Unit]
Description=ActivityWatch DLP Event Aggregator
After=activitywatch-server.service
[Service]
Type=oneshot
User={{ aw_server_user }}
WorkingDirectory={{ aw_server_data_dir }}
ExecStart=/usr/local/bin/dlp-aggregator-rust \
--aw-url http://127.0.0.1:{{ aw_server_port }}/api/0 \
--sqlite-path {{ aw_server_data_dir }}/dlp_warehouse.sqlite \
--state-path {{ aw_server_data_dir }}/dlp-aggregator-state.json
[Install]
WantedBy=multi-user.target
- name: Установить systemd timer для агрегатора
ansible.builtin.copy:
dest: /etc/systemd/system/activitywatch-dlp-aggregator.timer
content: |
[Unit]
Description=Run ActivityWatch DLP Aggregator every 5 minutes
[Timer]
OnCalendar=*:3/10:10
AccuracySec=30s
RandomizedDelaySec=30s
Persistent=false
[Install]
WantedBy=timers.target
- name: Включить и запустить таймер агрегатора
ansible.builtin.systemd:
name: activitywatch-dlp-aggregator.timer
enabled: true
state: started
daemon_reload: true
- name: Настроить IOC enrichment из Hayabusa Sigma
when: aw_dlp_ioc_enabled | default(false) | bool
block:
- name: Создать каталог IOC enrichment
ansible.builtin.file:
path: "{{ aw_dlp_ioc_workdir }}/{{ item }}"
state: directory
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
mode: "0755"
loop:
- ""
- output
- tmp
- name: Проверить локальный Rust extractor IOC из Sigma
ansible.builtin.stat:
path: "{{ aw_rust_release_dir }}/extract-ioc-from-sigma"
delegate_to: localhost
register: aw_extract_ioc_from_sigma_rust_binary
become: false
- name: Требовать Rust extractor IOC из Sigma
ansible.builtin.assert:
that:
- aw_extract_ioc_from_sigma_rust_binary.stat.exists | default(false)
fail_msg: "Missing Rust artifact: {{ aw_rust_release_dir }}/extract-ioc-from-sigma"
- name: Установить Rust extractor IOC из Sigma
ansible.builtin.copy:
src: "{{ aw_rust_release_dir }}/extract-ioc-from-sigma"
dest: /usr/local/bin/aw-extract-ioc-from-sigma
owner: root
group: root
mode: "0755"
- name: Установить wrapper refresh IOC
ansible.builtin.copy:
dest: /usr/local/bin/aw-dlp-ioc-refresh.sh
owner: root
group: root
mode: "0755"
content: |
#!/usr/bin/env bash
set -euo pipefail
WORKDIR="{{ aw_dlp_ioc_workdir }}"
OUTDIR="${WORKDIR}/output"
TMPDIR="${WORKDIR}/tmp"
RULES_DIR="${TMPDIR}/hayabusa-rules"
ZIP_PATH="${TMPDIR}/hayabusa-rules.zip"
mkdir -p "${OUTDIR}" "${TMPDIR}"
rm -rf "${RULES_DIR}"
curl -fsSL -o "${ZIP_PATH}" "{{ aw_dlp_ioc_rules_zip_url }}"
unzip -q -o "${ZIP_PATH}" -d "${TMPDIR}"
EXTRACTED_DIR=$(find "${TMPDIR}" -maxdepth 1 -type d -name 'hayabusa-rules-*' | head -n1)
if [ -z "${EXTRACTED_DIR}" ]; then
echo "ERROR: hayabusa-rules archive extraction failed" >&2
exit 1
fi
mv "${EXTRACTED_DIR}" "${RULES_DIR}"
/usr/local/bin/aw-extract-ioc-from-sigma \
--rules-root "${RULES_DIR}" \
--out-dir "${OUTDIR}"
ln -sfn "${OUTDIR}" "${WORKDIR}/latest"
- name: Установить systemd unit IOC refresh
ansible.builtin.copy:
dest: /etc/systemd/system/aw-dlp-ioc-refresh.service
owner: root
group: root
mode: "0644"
content: |
[Unit]
Description=Refresh DLP IOC blacklist from Hayabusa Sigma rules
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/aw-dlp-ioc-refresh.sh
- name: Установить systemd timer IOC refresh
ansible.builtin.copy:
dest: /etc/systemd/system/aw-dlp-ioc-refresh.timer
owner: root
group: root
mode: "0644"
content: |
[Unit]
Description=Run DLP IOC refresh from Hayabusa rules
[Timer]
OnBootSec={{ aw_dlp_ioc_refresh_on_boot_sec }}
OnUnitActiveSec={{ aw_dlp_ioc_refresh_interval }}
Persistent=true
Unit=aw-dlp-ioc-refresh.service
[Install]
WantedBy=timers.target
- name: Включить и запустить IOC refresh timer
ansible.builtin.systemd:
name: aw-dlp-ioc-refresh.timer
enabled: true
state: started
daemon_reload: true
- name: Выполнить принудительный refresh IOC
ansible.builtin.systemd:
name: aw-dlp-ioc-refresh.service
state: started
- name: Проверить наличие IOC артефактов после refresh
ansible.builtin.stat:
path: "{{ aw_dlp_ioc_workdir }}/output/{{ item }}"
register: aw_dlp_ioc_artifacts
loop:
- ioc_blacklist.json
- ioc_blacklist.csv
- ioc_blacklist.sql
- name: Assert по IOC артефактам
ansible.builtin.assert:
that:
- item.stat.exists
- (item.stat.size | int) > 100
fail_msg: "Не сгенерирован IOC артефакт: {{ item.stat.path | default('unknown') }}"
loop: "{{ aw_dlp_ioc_artifacts.results }}"
- name: Применить базовые worktime settings (classes)
ansible.builtin.uri:
url: "http://127.0.0.1:{{ aw_server_port }}/api/0/settings/classes"
method: POST
body: "{{ aw_worktime_classes }}"
body_format: json
status_code: [200, 201]
when: aw_apply_worktime_settings | default(false) | bool
- name: Применить базовые views для DLP и worktime
ansible.builtin.uri:
url: "http://127.0.0.1:{{ aw_server_port }}/api/0/settings/views"
method: POST
body: "{{ aw_default_views }}"
body_format: json
status_code: [200, 201]
when: aw_apply_worktime_settings | default(false) | bool
- name: Вычислить worktime durationDefault из aw_worktime_from/to
ansible.builtin.set_fact:
aw_worktime_duration_default_derived: >-
{{
(
(
(((aw_worktime_to | default('17:00')).split(':')[0] | int) * 60 + ((aw_worktime_to | default('17:00')).split(':')[1] | int)) -
(((aw_worktime_from | default('00:00')).split(':')[0] | int) * 60 + ((aw_worktime_from | default('00:00')).split(':')[1] | int))
) * 60
)
}}
when: aw_apply_worktime_settings | default(false) | bool
- name: Нормализовать durationDefault для ночных смен
ansible.builtin.set_fact:
aw_worktime_duration_default_effective: >-
{{
(aw_worktime_duration_default_derived | int)
if (aw_worktime_duration_default_derived | int) > 0
else ((aw_worktime_duration_default_derived | int) + 86400)
}}
when: aw_apply_worktime_settings | default(false) | bool
- name: Проверить корректность durationDefault
ansible.builtin.assert:
that:
- aw_worktime_duration_default_effective | int > 0
- aw_worktime_duration_default_effective | int <= 86400
fail_msg: "Некорректный интервал рабочего времени: {{ aw_worktime_from }}..{{ aw_worktime_to }}"
when: aw_apply_worktime_settings | default(false) | bool
- name: Применить базовый период worktime (startOfDay)
ansible.builtin.uri:
url: "http://127.0.0.1:{{ aw_server_port }}/api/0/settings/startOfDay"
method: POST
body: "\"{{ aw_worktime_start_of_day }}\""
headers:
Content-Type: application/json
status_code: [200, 201]
when: aw_apply_worktime_settings | default(false) | bool
- name: Применить базовый период worktime (durationDefault seconds)
ansible.builtin.uri:
url: "http://127.0.0.1:{{ aw_server_port }}/api/0/settings/durationDefault"
method: POST
body: "{{ aw_worktime_duration_default_effective | string }}"
headers:
Content-Type: application/json
status_code: [200, 201]
when: aw_apply_worktime_settings | default(false) | bool
- name: Применить always_active_pattern для fallback без AFK
ansible.builtin.uri:
url: "http://127.0.0.1:{{ aw_server_port }}/api/0/settings/always_active_pattern"
method: POST
body: "\"{{ aw_server_always_active_pattern }}\""
headers:
Content-Type: application/json
status_code: [200, 201]
when:
- aw_apply_worktime_settings | default(false) | bool
- (aw_server_always_active_pattern | default('') | string | length) > 0
- name: Применить landingpage профиля
ansible.builtin.uri:
url: "http://127.0.0.1:{{ aw_server_port }}/api/0/settings/landingpage"
method: POST
body: "\"{{ aw_server_landingpage }}\""
headers:
Content-Type: application/json
status_code: [200, 201]
when:
- aw_apply_worktime_settings | default(false) | bool
- (aw_server_landingpage | default('') | string | length) > 0
- name: Обновить IOC blacklist из hayabusa (если включено)
when:
- aw_hayabusa_ioc_refresh_enabled | default(false) | bool
- aw_hayabusa_rules_root is defined
- aw_hayabusa_ioc_output_dir is defined
block:
- name: Создать выходную директорию для IOC
ansible.builtin.file:
path: "{{ aw_hayabusa_ioc_output_dir }}"
state: directory
mode: "0755"
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
- name: Обновить IOC blacklist из hayabusa правил
ansible.builtin.shell:
cmd: |
set -euo pipefail
{{ aw_repo_root }}/scripts/build_dlp_ioc_from_hayabusa.sh \
"{{ aw_hayabusa_rules_root }}" \
"{{ aw_hayabusa_ioc_output_dir }}"
args:
chdir: "{{ aw_repo_root }}"
register: aw_hayabusa_ioc_refresh_result
changed_when: "'IOC artifacts generated' in aw_hayabusa_ioc_refresh_result.stdout"
- name: Показать результат обновления IOC
ansible.builtin.debug:
msg: "{{ aw_hayabusa_ioc_refresh_result.stdout }}"
when: aw_hayabusa_ioc_refresh_result.stdout is defined
- name: Установить server-side Hayabusa runner
when: aw_hayabusa_runner_enabled | default(false) | bool
block:
- name: Создать каталоги Hayabusa
ansible.builtin.file:
path: "{{ item }}"
state: directory
owner: root
group: root
mode: "0755"
loop:
- "{{ aw_hayabusa_root }}"
- "{{ aw_hayabusa_root }}/releases"
- "{{ aw_hayabusa_release_dir }}"
- "{{ aw_hayabusa_reports_dir }}"
- "{{ aw_hayabusa_state_dir }}"
- "{{ aw_hayabusa_inbox_dir }}"
- "{{ aw_hayabusa_archive_dir }}"
- "{{ aw_hayabusa_incoming_dir }}"
- "{{ aw_hayabusa_staging_dir }}"
- "{{ aw_hayabusa_archive_packages_dir }}"
- "{{ aw_hayabusa_archive_extracted_dir }}"
- "{{ aw_hayabusa_logs_dir }}"
- name: Скачать архив Hayabusa
ansible.builtin.get_url:
url: "{{ aw_hayabusa_download_url }}"
dest: "{{ aw_hayabusa_archive_path }}"
mode: "0644"
- name: Распаковать pinned Hayabusa release
ansible.builtin.unarchive:
src: "{{ aw_hayabusa_archive_path }}"
dest: "{{ aw_hayabusa_release_dir }}"
remote_src: true
creates: "{{ aw_hayabusa_release_dir }}/{{ aw_hayabusa_binary_name }}"
- name: Удалить временный архив Hayabusa после распаковки
ansible.builtin.file:
path: "{{ aw_hayabusa_archive_path }}"
state: absent
- name: Нормализовать права release Hayabusa
ansible.builtin.file:
path: "{{ aw_hayabusa_release_dir }}"
state: directory
owner: root
group: root
mode: "0755"
recurse: true
- name: Сделать бинарь Hayabusa исполняемым
ansible.builtin.file:
path: "{{ aw_hayabusa_release_dir }}/{{ aw_hayabusa_binary_name }}"
owner: root
group: root
mode: "0755"
state: file
- name: Создать canonical symlink на текущий релиз Hayabusa
ansible.builtin.file:
src: "{{ aw_hayabusa_release_dir }}"
dest: "{{ aw_hayabusa_current_link }}"
state: link
force: true
- name: Создать canonical symlink на бинарь Hayabusa
ansible.builtin.file:
src: "{{ aw_hayabusa_binary_name }}"
dest: "{{ aw_hayabusa_release_dir }}/hayabusa"
state: link
force: true
- name: Установить wrapper aw-hayabusa
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/hayabusa/aw-hayabusa.sh"
dest: /usr/local/bin/aw-hayabusa
owner: root
group: root
mode: "0755"
- name: Создать server-side ops bundle для Hayabusa
ansible.builtin.file:
path: "{{ item }}"
state: directory
owner: root
group: root
mode: "0755"
loop:
- /opt/activitywatch/aw-rus-ops
- /opt/activitywatch/aw-rus-ops/hayabusa
- /opt/activitywatch/aw-rus-ops/ansible
- /opt/activitywatch/aw-rus-ops/drop
- name: Положить исходный wrapper в server-side ops bundle
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/hayabusa/aw-hayabusa.sh"
dest: /opt/activitywatch/aw-rus-ops/hayabusa/aw-hayabusa.sh
owner: root
group: root
mode: "0755"
- name: Проверить локальный Rust helper link-case для Hayabusa
ansible.builtin.stat:
path: "{{ aw_rust_release_dir }}/aw-hayabusa-link-case-rust"
delegate_to: localhost
register: aw_hayabusa_link_case_rust_binary
become: false
- name: Установить Rust helper link-case для Hayabusa
ansible.builtin.copy:
src: "{{ aw_rust_release_dir }}/aw-hayabusa-link-case-rust"
dest: /usr/local/bin/aw-hayabusa-link-case-rust
owner: root
group: root
mode: "0755"
when: aw_hayabusa_link_case_rust_binary.stat.exists | default(false)
- name: Требовать Rust helper link-case для Hayabusa
ansible.builtin.assert:
that:
- aw_hayabusa_link_case_rust_binary.stat.exists | default(false)
fail_msg: "Missing Rust artifact: {{ aw_rust_release_dir }}/aw-hayabusa-link-case-rust"
- name: Установить helper link-case для Hayabusa
ansible.builtin.copy:
content: |
#!/usr/bin/env bash
set -euo pipefail
exec /usr/local/bin/aw-hayabusa-link-case-rust "$@"
dest: /usr/local/bin/aw-hayabusa-link-case
owner: root
group: root
mode: "0755"
- name: Проверить локальный Rust helper from-windows для Hayabusa
ansible.builtin.stat:
path: "{{ aw_rust_release_dir }}/aw-hayabusa-from-windows-rust"
delegate_to: localhost
register: aw_hayabusa_from_windows_rust_binary
become: false
- name: Установить Rust helper from-windows для Hayabusa
ansible.builtin.copy:
src: "{{ aw_rust_release_dir }}/aw-hayabusa-from-windows-rust"
dest: /usr/local/bin/aw-hayabusa-from-windows-rust
owner: root
group: root
mode: "0755"
when: aw_hayabusa_from_windows_rust_binary.stat.exists | default(false)
- name: Требовать Rust helper from-windows для Hayabusa
ansible.builtin.assert:
that:
- aw_hayabusa_from_windows_rust_binary.stat.exists | default(false)
fail_msg: "Missing Rust artifact: {{ aw_rust_release_dir }}/aw-hayabusa-from-windows-rust"
- name: Установить helper from-windows для Hayabusa
ansible.builtin.copy:
content: |
#!/usr/bin/env bash
set -euo pipefail
exec /usr/local/bin/aw-hayabusa-from-windows-rust "$@"
dest: /usr/local/bin/aw-hayabusa-from-windows
owner: root
group: root
mode: "0755"
- name: Положить README Hayabusa в server-side ops bundle
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/hayabusa/README.md"
dest: /opt/activitywatch/aw-rus-ops/hayabusa/README.md
owner: root
group: root
mode: "0644"
- name: Проверить локальный Rust helper autoprocess для Hayabusa
ansible.builtin.stat:
path: "{{ aw_rust_release_dir }}/aw-hayabusa-autoprocess-rust"
delegate_to: localhost
register: aw_hayabusa_autoprocess_rust_binary
become: false
- name: Установить Rust helper autoprocess для Hayabusa
ansible.builtin.copy:
src: "{{ aw_rust_release_dir }}/aw-hayabusa-autoprocess-rust"
dest: /usr/local/bin/aw-hayabusa-autoprocess-rust
owner: root
group: root
mode: "0755"
when: aw_hayabusa_autoprocess_rust_binary.stat.exists | default(false)
- name: Требовать Rust helper autoprocess для Hayabusa
ansible.builtin.assert:
that:
- aw_hayabusa_autoprocess_rust_binary.stat.exists | default(false)
fail_msg: "Missing Rust artifact: {{ aw_rust_release_dir }}/aw-hayabusa-autoprocess-rust"
- name: Установить helper autoprocess для Hayabusa
ansible.builtin.copy:
content: |
#!/usr/bin/env bash
set -euo pipefail
exec /usr/local/bin/aw-hayabusa-autoprocess-rust "$@"
dest: /usr/local/bin/aw-hayabusa-autoprocess
owner: root
group: root
mode: "0755"
- name: Проверить локальный Rust helper case-alert для Hayabusa
ansible.builtin.stat:
path: "{{ aw_rust_release_dir }}/aw-hayabusa-case-alert-rust"
delegate_to: localhost
register: aw_hayabusa_case_alert_rust_binary
become: false
- name: Установить Rust helper case-alert для Hayabusa
ansible.builtin.copy:
src: "{{ aw_rust_release_dir }}/aw-hayabusa-case-alert-rust"
dest: /usr/local/bin/aw-hayabusa-case-alert-rust
owner: root
group: root
mode: "0755"
when: aw_hayabusa_case_alert_rust_binary.stat.exists | default(false)
- name: Требовать Rust helper case-alert для Hayabusa
ansible.builtin.assert:
that:
- aw_hayabusa_case_alert_rust_binary.stat.exists | default(false)
fail_msg: "Missing Rust artifact: {{ aw_rust_release_dir }}/aw-hayabusa-case-alert-rust"
- name: Установить helper case-alert для Hayabusa
ansible.builtin.copy:
content: |
#!/usr/bin/env bash
set -euo pipefail
exec /usr/local/bin/aw-hayabusa-case-alert-rust "$@"
dest: /usr/local/bin/aw-hayabusa-case-alert
owner: root
group: root
mode: "0755"
- name: Установить systemd unit aw-hayabusa-drop.service
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/aw-hayabusa-drop.service"
dest: /etc/systemd/system/aw-hayabusa-drop.service
owner: root
group: root
mode: "0644"
notify: Перезагрузить systemd
- name: Установить systemd unit aw-hayabusa-drop.path
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/aw-hayabusa-drop.path"
dest: /etc/systemd/system/aw-hayabusa-drop.path
owner: root
group: root
mode: "0644"
notify: Перезагрузить systemd
- name: Включить и запустить aw-hayabusa-drop.path
ansible.builtin.systemd:
name: aw-hayabusa-drop.path
enabled: true
state: started
daemon_reload: true
- name: Проверить server-side runner через doctor
ansible.builtin.command:
cmd: /usr/local/bin/aw-hayabusa doctor
changed_when: false
- name: Проверить загрузку profiles Hayabusa
ansible.builtin.shell: /usr/local/bin/aw-hayabusa profiles > /tmp/aw-hayabusa-profiles.txt
args:
executable: /bin/bash
changed_when: false
- name: Проверить наличие standard profile у Hayabusa
ansible.builtin.shell: "grep -q 'standard:' /tmp/aw-hayabusa-profiles.txt"
args:
executable: /bin/bash
changed_when: false
- name: Post-deploy health gate (aw-rus-healthd)
when:
- not ansible_check_mode
- aw_server_post_deploy_health_check_enabled | default(true) | bool
block:
- name: Запустить /usr/local/bin/aw-rus-healthd-rust --json
ansible.builtin.command:
cmd: /usr/local/bin/aw-rus-healthd-rust --json
register: aw_post_deploy_health
changed_when: false
failed_when: false
- name: Показать результат aw-rus-healthd
ansible.builtin.debug:
msg: "{{ aw_post_deploy_health.stdout }}"
handlers:
- name: Перезагрузить systemd
ansible.builtin.systemd:
daemon_reload: true
- name: Перезапустить activitywatch
ansible.builtin.systemd:
name: activitywatch-server.service
state: restarted