--- - name: Preflight | Required vault variables are defined ansible.builtin.assert: that: "{{ item }} is defined and ({{ item }} | length) > 0" fail_msg: "{{ item }} is not defined. Add it to your ansible vault." quiet: true loop: "{{ hermes_required_vault_vars }}" tags: [hermes, preflight] - name: Preflight | Confirm docker CLI is available ansible.builtin.command: docker --version changed_when: false tags: [hermes, preflight] - name: Preflight | Get existing container state community.docker.docker_container_info: name: "{{ hermes_container_name }}" register: hermes_existing tags: [hermes, preflight] # Only enforce free ports when our container is not already running, # so redeploys stay idempotent. - name: Preflight | Ensure required ports are free ansible.builtin.wait_for: host: 127.0.0.1 port: "{{ item }}" state: stopped timeout: 3 loop: "{{ hermes_preflight_ports }}" when: not (hermes_existing.container.State.Running | default(false)) tags: [hermes, preflight] - name: Create project and data directories ansible.builtin.file: path: "{{ item }}" state: directory mode: "0755" loop: - "{{ hermes_project_dir }}" - "{{ hermes_data_dir }}" tags: [hermes] # Compose reads this as root on the host; the container never sees the file. - name: Template secrets env file ansible.builtin.template: src: hermes-secrets.env.j2 dest: "{{ hermes_secrets_env_file }}" owner: root group: root mode: "0600" no_log: true tags: [hermes] - name: Template docker compose file ansible.builtin.template: src: docker-compose.yml.j2 dest: "{{ hermes_project_dir }}/docker-compose.yml" mode: "0644" tags: [hermes] - name: Deploy hermes community.docker.docker_compose_v2: project_src: "{{ hermes_project_dir }}" pull: "{{ hermes_pull_policy }}" state: present tags: [hermes] - name: Verify gateway health ansible.builtin.uri: url: "http://127.0.0.1:{{ hermes_gateway_port }}/health" status_code: 200 register: hermes_health until: hermes_health.status == 200 retries: "{{ (hermes_wait_timeout | int) // 5 }}" delay: 5 when: hermes_api_server_enabled | bool tags: [hermes, verify] - name: Wait for dashboard port ansible.builtin.wait_for: host: "{{ hermes_dashboard_host }}" port: "{{ hermes_dashboard_port }}" timeout: "{{ hermes_wait_timeout }}" when: hermes_dashboard_enabled | bool tags: [hermes, verify] # Runs inside the container with the image's own venv (PyYAML is available # there) as the hermes user, so config.yaml stays owned by UID 10000. - name: Merge config.yaml overrides ansible.builtin.command: argv: - docker - exec - -i - --user - hermes - -e - "HERMES_CONFIG_OVERRIDES={{ hermes_config_overrides | to_json }}" - "{{ hermes_container_name }}" - /opt/hermes/.venv/bin/python - "-" stdin: "{{ lookup('ansible.builtin.file', 'merge_config.py') }}" register: hermes_config_merge changed_when: "'CHANGED' in hermes_config_merge.stdout and 'UNCHANGED' not in hermes_config_merge.stdout" no_log: true when: hermes_config_overrides | length > 0 notify: Restart hermes tags: [hermes, config]