blumeops/ansible/roles/kiwix/tasks/main.yml
Erich Blume 2a1359a3b6 Fix ansible handler timeouts for alloy and loki restarts (#12)
## Summary
- Use async with poll: 0 for alloy and loki restart handlers
- Fire-and-forget approach prevents ansible from hanging on graceful shutdown

## Test plan
- [x] Manually verified `brew services restart grafana-alloy` works
- [x] Run full ansible playbook and verify it completes without timeout

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Reviewed-on: https://forge.tail8d86e.ts.net/eblume/blumeops/pulls/12
2026-01-15 13:56:11 -08:00

212 lines
6.9 KiB
YAML

---
- name: Ensure kiwix ZIM directory exists
ansible.builtin.file:
path: "{{ kiwix_zim_dir }}"
state: directory
mode: '0755'
# --- Transmission-based download logic ---
- name: Check transmission daemon is responding
ansible.builtin.command: transmission-remote -l
register: transmission_check
changed_when: false
failed_when: false
when: kiwix_use_transmission
- name: Fail if transmission is not running
ansible.builtin.fail:
msg: "Transmission daemon is not responding. Ensure transmission role ran successfully."
when: kiwix_use_transmission and transmission_check.rc != 0
# Get all torrent statuses in a single call (much faster than looping)
- name: Get transmission torrent list
ansible.builtin.command: transmission-remote -l
register: transmission_list
changed_when: false
when: kiwix_use_transmission
# Parse torrent status for each ZIM archive from the cached list
- name: Check torrent status for each ZIM archive
ansible.builtin.shell: |
# Look for the torrent by filename in the cached list
torrent_line=$(echo "{{ transmission_list.stdout }}" | grep -F "{{ item.filename | regex_replace('\\.zim$', '') }}" || true)
if [ -z "$torrent_line" ]; then
echo "not_found"
else
pct=$(echo "$torrent_line" | awk '{print $2}')
if [ "$pct" = "100%" ]; then
echo "complete"
else
echo "downloading $pct"
fi
fi
args:
executable: /bin/bash
loop: "{{ kiwix_zim_archives }}"
loop_control:
label: "{{ item.filename }}"
register: torrent_status
changed_when: false
when: kiwix_use_transmission
# Add torrents that are not yet loaded
- name: Add missing torrents to transmission
ansible.builtin.command: >
transmission-remote -a "{{ kiwix_torrent_base_url }}/{{ item.item.category }}/{{ item.item.filename }}.torrent"
loop: "{{ torrent_status.results | default([]) }}"
loop_control:
label: "{{ item.item.filename }}"
when:
- kiwix_use_transmission
- item.stdout is defined
- item.stdout == "not_found"
register: torrent_add
changed_when: torrent_add.rc == 0
# Wait briefly and recheck status for newly added torrents
- name: Wait for transmission to register new torrents
ansible.builtin.pause:
seconds: 5
when:
- kiwix_use_transmission
- torrent_add.changed is defined
- torrent_add.changed
# Only recheck if we actually added new torrents
- name: Get updated transmission torrent list
ansible.builtin.command: transmission-remote -l
register: transmission_list_updated
changed_when: false
when:
- kiwix_use_transmission
- torrent_add.changed | default(false)
# Recheck torrent statuses only if new torrents were added
- name: Recheck torrent status after adding
ansible.builtin.shell: |
torrent_line=$(echo "{{ transmission_list_updated.stdout }}" | grep -F "{{ item.filename | regex_replace('\\.zim$', '') }}" || true)
if [ -z "$torrent_line" ]; then
echo "not_found"
else
pct=$(echo "$torrent_line" | awk '{print $2}')
if [ "$pct" = "100%" ]; then
echo "complete"
else
echo "downloading $pct"
fi
fi
args:
executable: /bin/bash
loop: "{{ kiwix_zim_archives }}"
loop_control:
label: "{{ item.filename }}"
register: torrent_status_recheck
changed_when: false
when:
- kiwix_use_transmission
- torrent_add.changed | default(false)
# Use rechecked status if available, otherwise use initial status
- name: Set final torrent status
ansible.builtin.set_fact:
torrent_status_final: "{{ torrent_status_recheck if (torrent_add.changed | default(false)) else torrent_status }}"
when: kiwix_use_transmission
# Check if symlink already exists for completed downloads
- name: Check if ZIM symlink exists
ansible.builtin.stat:
path: "{{ kiwix_zim_dir }}/{{ item.item.filename }}"
get_checksum: false
loop: "{{ torrent_status_final.results | default([]) }}"
loop_control:
label: "{{ item.item.filename }}"
register: zim_symlink_stat
when:
- kiwix_use_transmission
- item.stdout is defined
- item.stdout == "complete"
# Create symlinks for completed downloads
- name: Symlink completed ZIM downloads to kiwix directory
ansible.builtin.file:
src: "{{ transmission_download_dir }}/{{ item.item.item.filename }}"
dest: "{{ kiwix_zim_dir }}/{{ item.item.item.filename }}"
state: link
loop: "{{ zim_symlink_stat.results | default([]) }}"
loop_control:
label: "{{ item.item.item.filename | default('unknown') }}"
when:
- kiwix_use_transmission
- item.stat is defined
- not item.stat.exists
notify: restart kiwix-serve
# Report on incomplete downloads (informational, no failure)
- name: Report incomplete torrent downloads
ansible.builtin.debug:
msg: "Torrent still downloading: {{ item.item.filename }} ({{ item.stdout }})"
loop: "{{ torrent_status_final.results | default([]) }}"
loop_control:
label: "{{ item.item.filename }}"
when:
- kiwix_use_transmission
- item.stdout is defined
- item.stdout != "complete"
- item.stdout != "not_found"
# --- Fallback: Direct HTTP download (original behavior) ---
- name: Check which ZIM archives exist (direct download mode)
ansible.builtin.stat:
path: "{{ kiwix_zim_dir }}/{{ item.filename }}"
get_checksum: false
loop: "{{ kiwix_zim_archives }}"
loop_control:
label: "{{ item.filename }}"
register: zim_stat
when: not kiwix_use_transmission
- name: Download missing ZIM archives (direct download mode)
ansible.builtin.get_url:
url: "https://download.kiwix.org/zim/{{ item.item.category }}/{{ item.item.filename }}"
dest: "{{ kiwix_zim_dir }}/{{ item.item.filename }}"
mode: '0644'
timeout: 3600
loop: "{{ zim_stat.results | default([]) }}"
loop_control:
label: "{{ item.item.filename | default('unknown') }}"
when:
- not kiwix_use_transmission
- item.stat is defined
- not item.stat.exists
notify: restart kiwix-serve
# --- Determine which archives are available ---
- name: Find available ZIM archives in kiwix directory
ansible.builtin.find:
paths: "{{ kiwix_zim_dir }}"
patterns: "*.zim"
file_type: any # includes symlinks
register: available_zim_files
- name: Build list of available archive filenames
ansible.builtin.set_fact:
kiwix_available_archives: "{{ available_zim_files.files | map(attribute='path') | map('basename') | list }}"
# --- LaunchAgent deployment ---
- name: Deploy kiwix-serve LaunchAgent plist
ansible.builtin.template:
src: kiwix-serve.plist.j2
dest: ~/Library/LaunchAgents/mcquack.eblume.kiwix-serve.plist
mode: '0644'
notify: restart kiwix-serve
- name: Check if kiwix-serve LaunchAgent is loaded
ansible.builtin.command: launchctl list mcquack.eblume.kiwix-serve
register: launchctl_check
changed_when: false
failed_when: false
- name: Load kiwix-serve LaunchAgent if not loaded
ansible.builtin.command: launchctl load ~/Library/LaunchAgents/mcquack.eblume.kiwix-serve.plist
when: launchctl_check.rc != 0
failed_when: false