mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-06 10:59:59 +00:00
200 lines
8.5 KiB
YAML
200 lines
8.5 KiB
YAML
---
|
|
# Lab-only node provisioning for the simulated cluster; never a production
|
|
# role. Runs over ansible_connection: docker right after `compose up` (python +
|
|
# ansible + the CLI are baked into the node image via the distro's infinito
|
|
# image, so no .deb bootstrap is needed): waits for systemd, wires lab DNS
|
|
# (sys-hostname skips /etc/hosts on DOCKER_IN_CONTAINER hosts; the dnsmasq
|
|
# wildcard points the app domain at the manager's ingress), then unpacks the
|
|
# current repo onto every node. Host-side concerns (image build, compose up)
|
|
# live in scripts/tests/deploy/swarm/routine/01_bootstrap.sh.
|
|
- name: provision the simulated cluster nodes
|
|
hosts: all
|
|
gather_facts: false
|
|
vars_files:
|
|
- "{{ playbook_dir }}/../../group_vars/all/08_networks.yml" # nocheck: path-absolute - lab-only playbook, playbook_dir is stable and path_absolute plugin loading is fragile in a standalone -c docker run
|
|
vars:
|
|
lab_repo_root: "{{ playbook_dir }}/../.." # nocheck: path-absolute - see above
|
|
lab_mgr: "{{ lookup('env', 'MGR') }}"
|
|
lab_wrk1: "{{ lookup('env', 'WRK1') }}"
|
|
lab_wrk2: "{{ lookup('env', 'WRK2') }}"
|
|
lab_nfs: "{{ lookup('env', 'NFS_SERVER') }}"
|
|
lab_backup: "{{ lookup('env', 'BACKUP_NODE') }}"
|
|
lab_domain: "{{ lookup('env', 'INFINITO_DOMAIN') }}"
|
|
lab_export_base: "{{ lookup('env', 'NFS_EXPORT_BASE') }}"
|
|
lab_node_src: "{{ lookup('env', 'INFINITO_NODE_SRC_DIR') }}"
|
|
lab_runner_temp: "{{ lookup('env', 'RUNNER_TEMP') }}"
|
|
lab_sampler_log: "{{ lookup('env', 'INFINITO_DNS53_SAMPLER_LOG') }}"
|
|
lab_systemd_timeout: "{{ lookup('env', 'SWARM_PILOT_SYSTEMD_TIMEOUT') | default('180', true) }}"
|
|
lab_is_mgr: "{{ inventory_hostname == lab_mgr }}"
|
|
lab_is_worker: "{{ inventory_hostname in [lab_wrk1, lab_wrk2] }}"
|
|
lab_dns_node: "{{ lab_is_mgr or lab_is_worker or inventory_hostname == lab_nfs }}"
|
|
lab_domain_target: "{{ lookup('env', 'INFINITO_SWARM_MGR_IP') }}"
|
|
lab_filesystem: "{{ lookup('env', 'INFINITO_DOCKER_FILESYSTEM') }}"
|
|
lab_filesystem_required: "{{ lookup('env', 'INFINITO_DOCKER_FILESYSTEM_REQUIRED') | default('false', true) }}"
|
|
lab_dataroot_size: "{{ '60G' if lab_is_mgr else '30G' }}"
|
|
lab_no_proxy: "localhost,127.0.0.1,::1,infinito-registry-cache,{{ lab_mgr }},{{ lab_wrk1 }},{{ lab_wrk2 }},{{ lab_nfs }},{{ lab_backup }},gcr.io,storage.googleapis.com,googleusercontent.com"
|
|
tasks:
|
|
- name: require the lab manager IP (lookup('env') yields '' for a missing key, and an empty dnsmasq address= is valid syntax)
|
|
assert:
|
|
that: lab_domain_target | length > 0
|
|
fail_msg: INFINITO_SWARM_MGR_IP is empty; it comes from scripts/tests/deploy/swarm/utils/topology/base.sh
|
|
run_once: true
|
|
|
|
- block:
|
|
- name: wait for systemd ready (status from stdout; rc is nonzero when degraded)
|
|
command: systemctl is-system-running
|
|
timeout: 15
|
|
register: lab_systemd
|
|
until: lab_systemd.stdout is search('running|degraded|starting|maintenance')
|
|
failed_when: lab_systemd.stdout is not search('running|degraded|starting|maintenance')
|
|
retries: "{{ lab_systemd_timeout }}"
|
|
delay: 1
|
|
changed_when: false
|
|
rescue:
|
|
- name: dump docker logs
|
|
command:
|
|
argv: [docker, logs, "{{ inventory_hostname }}"]
|
|
timeout: 30
|
|
delegate_to: localhost
|
|
ignore_errors: true
|
|
changed_when: false
|
|
- name: dump journal + pending jobs
|
|
command: "{{ item }}"
|
|
loop:
|
|
- journalctl --no-pager -n 50
|
|
- systemctl list-jobs --no-pager
|
|
timeout: 30
|
|
ignore_errors: true
|
|
changed_when: false
|
|
- name: dump container state
|
|
command:
|
|
argv: [docker, inspect, --format, "{{ '{{json .State}}' }}", "{{ inventory_hostname }}"]
|
|
timeout: 30
|
|
delegate_to: localhost
|
|
ignore_errors: true
|
|
changed_when: false
|
|
- name: fail the bring-up
|
|
fail:
|
|
msg: "{{ inventory_hostname }} systemd did not become responsive within {{ lab_systemd_timeout }}s"
|
|
|
|
- name: permit user logins (degraded lab boot never clears /run/nologin)
|
|
systemd:
|
|
name: systemd-user-sessions
|
|
state: started
|
|
timeout: 30
|
|
|
|
- name: put the node docker data root on the stated filesystem (before anything is pulled)
|
|
script: >-
|
|
{{ lab_repo_root }}/scripts/tests/deploy/utils/filesystem/docker_dataroot.sh
|
|
{{ lab_filesystem }} {{ lab_filesystem_required }} {{ lab_dataroot_size }} {{ inventory_hostname }}
|
|
timeout: 600
|
|
when: lab_filesystem | length > 0
|
|
changed_when: true
|
|
register: lab_dataroot
|
|
|
|
- name: surface the node's effective data root filesystem
|
|
debug:
|
|
msg: "{{ lab_dataroot.stdout_lines | select('search', '^docker-dataroot-filesystem: status=') | list }}"
|
|
when: not (lab_dataroot is skipped)
|
|
|
|
- name: probe the registry-cache CA (mounted by cache.override.yml, absent without a local cache stack)
|
|
stat:
|
|
path: /opt/registry-cache-ca/ca.crt
|
|
timeout: 30
|
|
register: lab_registry_ca
|
|
|
|
- name: wire the node docker daemon to the host registry cache
|
|
include_tasks: registry_cache.yml
|
|
when: lab_registry_ca.stat.exists
|
|
|
|
- name: wipe stale NFS export state (as root in-node; the act runner cannot)
|
|
command: find {{ lab_export_base }} -mindepth 1 -delete
|
|
timeout: 120
|
|
when: inventory_hostname == lab_nfs
|
|
changed_when: true
|
|
|
|
- name: render the app-domain hosts entries
|
|
command: python3 -m utils.tests.swarm.write.hosts_entries
|
|
args:
|
|
chdir: "{{ lab_repo_root }}"
|
|
environment:
|
|
HOSTS_ENTRY_IP: "{{ lab_domain_target }}"
|
|
timeout: 60
|
|
register: lab_hosts_entries
|
|
when: lab_is_mgr or inventory_hostname in [lab_nfs, lab_backup]
|
|
delegate_to: localhost
|
|
changed_when: false
|
|
|
|
- name: seed /etc/hosts with the app domains
|
|
blockinfile:
|
|
path: /etc/hosts
|
|
marker: "# {mark} INFINITO LAB DOMAINS"
|
|
block: "{{ lab_hosts_entries.stdout }}"
|
|
unsafe_writes: true
|
|
timeout: 30
|
|
when: lab_is_mgr or inventory_hostname in [lab_nfs, lab_backup]
|
|
|
|
- name: own the whole dnsmasq config (the packaging appends --local-service unconditionally and only an interface, except-interface, listen-address or auth-server directive resets it; without that reset a failed interface re-enumeration empties dnsmasq's local-subnet list and it rejects every query, loopback included, until an address event rebuilds it)
|
|
template: # nocheck: stack-host-template - lab node system config, every DNS node writes its own /etc/dnsmasq.conf and IS_STACK_HOST does not exist in this play
|
|
src: dnsmasq.conf.j2
|
|
dest: /etc/dnsmasq.conf
|
|
timeout: 30
|
|
when: lab_dns_node
|
|
|
|
- name: enable and restart dnsmasq (arch is Type=dbus, so systemd waits its full 90s DefaultTimeoutStartSec before reporting)
|
|
systemd:
|
|
name: dnsmasq
|
|
enabled: true
|
|
state: restarted
|
|
timeout: 120
|
|
when: lab_dns_node
|
|
|
|
- name: point resolv.conf at dnsmasq
|
|
copy:
|
|
dest: /etc/resolv.conf
|
|
content: "nameserver 127.0.0.1\n"
|
|
unsafe_writes: true
|
|
timeout: 30
|
|
when: lab_dns_node
|
|
|
|
- name: verify the app domain resolves to its lab target
|
|
command: getent ahosts {{ ('test.' ~ lab_domain) if lab_is_worker else lab_domain }}
|
|
timeout: 10
|
|
register: lab_resolve
|
|
until: lab_resolve.stdout is search('^' ~ (lab_domain_target | regex_escape) ~ ' ', multiline=True)
|
|
retries: 30
|
|
delay: 1
|
|
changed_when: false
|
|
when: lab_dns_node
|
|
|
|
- name: pack the repo once on the controller
|
|
command: tar -C {{ lab_repo_root }} -cf {{ lab_runner_temp }}/infinito-src.tar .
|
|
timeout: 300
|
|
delegate_to: localhost
|
|
run_once: true
|
|
changed_when: true
|
|
|
|
- name: create the node source dir
|
|
file:
|
|
path: "{{ lab_node_src }}"
|
|
state: directory
|
|
mode: "0755"
|
|
timeout: 30
|
|
|
|
- name: unpack the repo onto the node
|
|
unarchive:
|
|
src: "{{ lab_runner_temp }}/infinito-src.tar"
|
|
dest: "{{ lab_node_src }}"
|
|
timeout: 300
|
|
|
|
- name: sample what the resolver answers, not just whether it listens
|
|
shell: |
|
|
set -eu
|
|
sampler={{ lab_node_src }}/scripts/tests/deploy/ci/dns53-sampler.sh
|
|
INFINITO_DNS53_SAMPLER_LOG={{ lab_sampler_log }} \
|
|
setsid sh "${sampler}" </dev/null >/dev/null 2>&1 &
|
|
args:
|
|
creates: "{{ lab_sampler_log }}"
|
|
timeout: 30
|
|
when: lab_dns_node
|