semaphore/life-church/playbooks/lc-precheck.yml

145 lines
6.8 KiB
YAML

---
# ============================================================================
# life-church/playbooks/lc-precheck.yml
# Pre-checks + fact gathering for Life Church desktops (thinkcenter, tc1).
# READ-ONLY: gathers facts and asserts baseline conditions. Changes nothing.
#
# become (sudo) password is fetched from Infisical /lc-hosts at runtime on
# localhost, then applied per-host via ansible_become_pass. Never hardcoded.
# ============================================================================
# ---------------------------------------------------------------------------
# Play 1 (localhost): resolve Infisical creds + read per-host sudo passwords
# ---------------------------------------------------------------------------
- name: "Life Church pre-check — resolve become passwords from Infisical"
hosts: localhost
gather_facts: false
tasks:
- name: "[resolve] Infisical creds from env (Semaphore environment)"
ansible.builtin.set_fact:
infisical_client_id: "{{ lookup('env','INFISICAL_CLIENT_ID') }}"
infisical_client_secret: "{{ lookup('env','INFISICAL_CLIENT_SECRET') }}"
infisical_project_id: "{{ lookup('env','INFISICAL_PROJECT_ID') }}"
infisical_url: "{{ lookup('env','INFISICAL_API_URL') | default('http://192.168.122.41:8080', true) }}"
infisical_env_slug: "{{ lookup('env','INFISICAL_ENV_SLUG') | default('prod', true) }}"
- name: "[resolve] Assert Infisical creds present"
ansible.builtin.assert:
that:
- infisical_client_id | length > 0
- infisical_client_secret | length > 0
- infisical_project_id | length > 0
fail_msg: "Infisical creds missing from environment — check Semaphore environment 'infisical-dev'."
- name: "[infisical] Log in"
infisical.vault.login:
url: "{{ infisical_url }}"
auth_method: universal_auth
universal_auth_client_id: "{{ infisical_client_id }}"
universal_auth_client_secret: "{{ infisical_client_secret }}"
register: infisical_login
no_log: true
- name: "[infisical] Read /lc-hosts secrets"
infisical.vault.read_secrets:
login_data: "{{ infisical_login.login_data }}"
project_id: "{{ infisical_project_id }}"
env_slug: "{{ infisical_env_slug }}"
path: "/lc-hosts"
as_dict: true
register: lc_secrets
no_log: true
- name: "[set] Stash become passwords keyed by host (localhost hostvars)"
ansible.builtin.set_fact:
become_pass_map:
thinkcenter: "{{ lc_secrets.secrets['THINKCENTER_SUDO_PASS'] }}"
tc1: "{{ lc_secrets.secrets['TC1_SUDO_PASS'] }}"
no_log: true
# ---------------------------------------------------------------------------
# Play 2 (the desktops): connectivity, facts, and read-only pre-checks
# ---------------------------------------------------------------------------
- name: "Life Church pre-check — connectivity + facts + baseline checks"
hosts: lifechurch_desktops
gather_facts: true
become: true
vars:
# pull this host's sudo pass from the map computed on localhost in Play 1
ansible_become_pass: "{{ hostvars['localhost'].become_pass_map[inventory_hostname] }}"
tasks:
- name: "[net] Host reachable (SSH connection established)"
ansible.builtin.ping:
- name: "[sudo] Privilege escalation works"
ansible.builtin.command: id -u
register: id_check
changed_when: false
- name: "[sudo] Confirm running as root after become"
ansible.builtin.assert:
that: id_check.stdout == "0"
fail_msg: "become did not escalate to root on {{ inventory_hostname }}"
success_msg: "sudo OK on {{ inventory_hostname }}"
- name: "[disk] Root filesystem usage"
ansible.builtin.set_fact:
root_mount: "{{ ansible_mounts | selectattr('mount','equalto','/') | first }}"
- name: "[disk] Assert root filesystem has >10% free"
ansible.builtin.assert:
that: (root_mount.size_available / root_mount.size_total) > 0.10
fail_msg: "LOW DISK on {{ inventory_hostname }}: only {{ (100 * root_mount.size_available / root_mount.size_total) | round(1) }}% free"
success_msg: "Disk OK: {{ (100 * root_mount.size_available / root_mount.size_total) | round(1) }}% free"
- name: "[mem] Assert at least 200MB RAM free"
ansible.builtin.assert:
that: ansible_memfree_mb > 200
fail_msg: "LOW MEMORY on {{ inventory_hostname }}: {{ ansible_memfree_mb }}MB free"
success_msg: "Memory OK: {{ ansible_memfree_mb }}MB free of {{ ansible_memtotal_mb }}MB"
- name: "[time] Check NTP/clock sync status"
ansible.builtin.command: timedatectl show -p NTPSynchronized --value
register: ntp_sync
changed_when: false
failed_when: false
- name: "[pkg] Count pending apt security updates"
ansible.builtin.shell: >-
set -o pipefail;
apt-get -s -o Debug::NoLocking=true upgrade 2>/dev/null | grep -c '^Inst' || true
args:
executable: /bin/bash
register: pending_updates
changed_when: false
failed_when: false
- name: "[reboot] Reboot-required flag present?"
ansible.builtin.stat:
path: /var/run/reboot-required
register: reboot_required
- name: "[report] Host summary"
ansible.builtin.debug:
msg:
- "===== {{ inventory_hostname }} ({{ ansible_host }}) ====="
- "OS : {{ ansible_distribution }} {{ ansible_distribution_version }} | kernel {{ ansible_kernel }}"
- "CPU / RAM : {{ ansible_processor_vcpus }} vcpus | {{ ansible_memtotal_mb }}MB total, {{ ansible_memfree_mb }}MB free"
- "Root disk : {{ (root_mount.size_total / 1073741824) | round(1) }}GB total, {{ (root_mount.size_available / 1073741824) | round(1) }}GB free ({{ (100 * root_mount.size_available / root_mount.size_total) | round(1) }}% free)"
- "Uptime : {{ (ansible_uptime_seconds / 3600) | round(1) }} hours"
- "Clock synced : {{ 'yes' if ntp_sync.stdout == 'yes' else 'NO — check time sync' }}"
- "Pending pkgs : {{ pending_updates.stdout | trim }} upgradable"
- "Reboot needed : {{ 'YES' if reboot_required.stat.exists else 'no' }}"
- "Default IPv4 : {{ ansible_default_ipv4.address | default('n/a') }} ({{ ansible_default_ipv4.interface | default('n/a') }})"
# ---------------------------------------------------------------------------
# Play 3 (localhost): overall result
# ---------------------------------------------------------------------------
- name: "Life Church pre-check — result"
hosts: localhost
gather_facts: false
tasks:
- name: "[result] ALL PRE-CHECKS PASSED"
ansible.builtin.debug:
msg: "Pre-checks passed for all Life Church desktops — hosts reachable, sudo OK, resources healthy."