--- - name: Проверить обязательные переменные CT ansible.builtin.assert: that: - ct_id is defined - ct_hostname is defined - ct_storage is defined - ct_template is defined - ct_rootfs_size is defined - ct_cores is defined - ct_memory is defined - ct_swap is defined - ct_bridge is defined - ct_ip is defined - ct_gw is defined - ct_password is defined - ct_unprivileged is defined - ct_onboot is defined - ct_features is defined - aw_repo_root is defined - aw_server_version is defined - aw_server_download_url is defined - aw_server_bind_host is defined - aw_server_port is defined - aw_server_webui_dir is defined - aw_server_data_dir is defined - aw_server_log_dir is defined - aw_server_user is defined - aw_server_group is defined fail_msg: "Не заданы обязательные переменные для создания CT и развёртывания." - name: Сформировать сетевую строку CT ansible.builtin.set_fact: ct_net0: >- name=eth0,bridge={{ ct_bridge }},ip={{ ct_ip }},gw={{ ct_gw }}{% if (ct_vlan | default('') | string | length) > 0 %},tag={{ ct_vlan }}{% endif %} - name: Проверить, существует ли CT ansible.builtin.command: argv: - pct - status - "{{ ct_id }}" register: ct_status_check failed_when: false changed_when: false - name: Создать CT, если он отсутствует ansible.builtin.command: argv: - pct - create - "{{ ct_id }}" - "{{ ct_template }}" - --hostname - "{{ ct_hostname }}" - --cores - "{{ ct_cores }}" - --memory - "{{ ct_memory }}" - --swap - "{{ ct_swap }}" - --rootfs - "{{ ct_storage }}:{{ ct_rootfs_size }}" - --password - "{{ ct_password }}" - --unprivileged - "{{ ct_unprivileged }}" - --onboot - "{{ ct_onboot }}" - --features - "{{ ct_features }}" - --net0 - "{{ ct_net0 }}" - --nameserver - "{{ ct_nameserver | default('') }}" - --searchdomain - "{{ ct_searchdomain | default('') }}" - --ostype - debian when: ct_status_check.rc != 0 no_log: true - name: Проверить текущее состояние CT ansible.builtin.command: argv: - pct - status - "{{ ct_id }}" register: ct_runtime_status changed_when: false - name: Запустить CT, если он остановлен ansible.builtin.command: argv: - pct - start - "{{ ct_id }}" when: "'stopped' in ct_runtime_status.stdout" - name: Создать bootstrap каталог на Proxmox host ansible.builtin.file: path: "{{ item }}" state: directory mode: "0700" loop: - "{{ proxmox_bootstrap_dir }}" - "{{ proxmox_bootstrap_dir }}/settings" - name: Скопировать AW bootstrap файлы во временный каталог Proxmox host ansible.builtin.copy: src: "{{ aw_repo_root }}/aw-server/{{ item }}" dest: "{{ proxmox_bootstrap_dir }}/{{ item }}" mode: "0644" loop: "{{ aw_bootstrap_files }}" - name: Установить базовые зависимости ОС внутри CT ansible.builtin.command: argv: - pct - exec - "{{ ct_id }}" - -- - bash - -lc - | set -euo pipefail export DEBIAN_FRONTEND=noninteractive apt-get update apt-get install -y curl ca-certificates bash unzip xz-utils jq rsync openssh-server python3 mkdir -p /opt/detmir/bootstrap/settings /etc/activitywatch systemctl enable ssh || true systemctl restart ssh || true register: ct_bootstrap_result retries: 10 delay: 6 until: ct_bootstrap_result.rc == 0 - name: Передать bootstrap файлы внутрь CT ansible.builtin.command: argv: - pct - push - "{{ ct_id }}" - "{{ proxmox_bootstrap_dir }}/{{ item }}" - "/opt/detmir/bootstrap/{{ item }}" loop: "{{ aw_bootstrap_files }}" - name: Записать AW server env во временный каталог Proxmox host ansible.builtin.copy: dest: "{{ proxmox_bootstrap_dir }}/aw-server.env" mode: "0600" content: | AW_SERVER_VERSION={{ aw_server_version }} AW_SERVER_DOWNLOAD_URL={{ aw_server_download_url }} AW_SERVER_BIND_HOST={{ aw_server_bind_host }} AW_SERVER_PORT={{ aw_server_port }} AW_SERVER_WEBUI_DIR={{ aw_server_webui_dir }} AW_SERVER_DATA_DIR={{ aw_server_data_dir }} AW_SERVER_LOG_DIR={{ aw_server_log_dir }} AW_SERVER_USER={{ aw_server_user }} AW_SERVER_GROUP={{ aw_server_group }} AW_SERVER_URL=http://127.0.0.1:{{ aw_server_port }} AW_WORKTIME_REPORT_BASE={{ aw_worktime_report_base }} AW_WORKTIME_TZ={{ aw_worktime_timezone }} no_log: true - name: Передать AW server env внутрь CT ansible.builtin.command: argv: - pct - push - "{{ ct_id }}" - "{{ proxmox_bootstrap_dir }}/aw-server.env" - /etc/activitywatch/aw-server.env no_log: true - name: Настроить права env файла внутри CT ansible.builtin.command: argv: - pct - exec - "{{ ct_id }}" - -- - chmod - "0600" - /etc/activitywatch/aw-server.env - name: Установить сервер и применить RU patch внутри CT ansible.builtin.command: argv: - pct - exec - "{{ ct_id }}" - -- - bash - -lc - | set -euo pipefail chmod +x /opt/detmir/bootstrap/install_aw_server.sh /opt/detmir/bootstrap/apply_webui_ru_patch.sh bash /opt/detmir/bootstrap/install_aw_server.sh bash /opt/detmir/bootstrap/apply_webui_ru_patch.sh systemctl restart activitywatch-server.service - name: Проверить AW API изнутри CT ansible.builtin.command: argv: - pct - exec - "{{ ct_id }}" - -- - bash - -lc - "curl -fsS http://127.0.0.1:{{ aw_server_port }}/api/0/info >/dev/null" - name: Проверить hooks RU patch в index.html ansible.builtin.command: argv: - pct - exec - "{{ ct_id }}" - -- - bash - -lc - "grep -q 'ru-patch-v5.js' {{ aw_server_webui_dir }}/index.html && grep -q 'sw-cleanup.js' {{ aw_server_webui_dir }}/index.html" - name: Показать итоговый endpoint ansible.builtin.debug: msg: - "CT {{ ct_id }} создан и настроен." - "Endpoint ActivityWatch: http://{{ ct_ip | regex_replace('/[0-9]+$', '') }}:{{ aw_server_port }}"