feat(dns): rewrite add_service_route.yml to support multi-host Traefik configs

- Parse Host() rules from router definitions
- Supports multiple hostnames per service file (e.g. semaphore + imagineering)
- More robust and future-proof
This commit is contained in:
Hermes Agent service account
2026-05-27 21:31:41 -05:00
parent dc3c0d7cb1
commit f962d0a6d7

View File

@@ -6,7 +6,8 @@
# #
# 1. Syncs boilerplates/traefik/dynamic/ to lightning-lane # 1. Syncs boilerplates/traefik/dynamic/ to lightning-lane
# 2. Scans the directory for service configs # 2. Scans the directory for service configs
# 3. Creates CNAME records for each service -> lightning-lane # 3. Extracts all hostnames from Host() rules (supports multi-host)
# 4. Creates CNAME records for each hostname -> lightning-lane
# #
# PREREQUISITES: # PREREQUISITES:
# - Service dynamic config YAML committed to boilerplates/traefik/dynamic/ # - Service dynamic config YAML committed to boilerplates/traefik/dynamic/
@@ -14,15 +15,6 @@
# #
# USAGE: # USAGE:
# ansible-playbook -i inventory.yml playbooks/add_service_route.yml # ansible-playbook -i inventory.yml playbooks/add_service_route.yml
#
# ADDING A NEW SERVICE:
# 1. Create boilerplates/traefik/dynamic/<service>.yml
# 2. Commit and push
# 3. Run this playbook
#
# EXCLUDING FILES:
# Files that are not service routes (e.g., default.yml for middleware
# definitions) should be added to the exclude_configs list below.
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
- name: Sync Traefik routes and ensure DNS records - name: Sync Traefik routes and ensure DNS records
@@ -39,7 +31,6 @@
dynamic_config_dir: "{{ playbook_dir }}/../../boilerplates/traefik/dynamic" dynamic_config_dir: "{{ playbook_dir }}/../../boilerplates/traefik/dynamic"
# Files in the dynamic directory that are NOT service routes # Files in the dynamic directory that are NOT service routes
# (middleware definitions, TLS options, etc.)
exclude_configs: exclude_configs:
- default.yml - default.yml
@@ -53,38 +44,53 @@
register: sync_result register: sync_result
changed_when: "'sending incremental file list' in sync_result.stdout" changed_when: "'sending incremental file list' in sync_result.stdout"
# ── Step 2: Discover service configs ── # ── Step 2: Discover hostnames from Traefik router rules ──
- name: Find all dynamic config files - name: Find all dynamic config files
ansible.builtin.find: ansible.builtin.find:
paths: "{{ dynamic_config_dir }}" paths: "{{ dynamic_config_dir }}"
patterns: "*.yml" patterns: "*.yml"
register: config_files register: config_files
- name: Build service list from config filenames - name: Read config files
ansible.builtin.set_fact: ansible.builtin.slurp:
service_names: >- src: "{{ item.path }}"
{{ config_files.files register: slurped_configs
| map(attribute='path') loop: "{{ config_files.files }}"
| map('basename') when: item.path | basename not in exclude_configs
| reject('in', exclude_configs)
| map('regex_replace', '\.yml$', '')
| list }}
- name: Display services to route - name: Extract all hostnames from Host() rules
ansible.builtin.set_fact:
hostnames: >-
{{
slurped_configs.results
| selectattr('content', 'defined')
| map(attribute='content')
| map('b64decode')
| map('regex_findall', 'Host\\(`([^`]+)`\\)')
| flatten
| map('split', ' || ')
| flatten
| map('regex_replace', '`', '')
| select('match', '.*\\.local\\.mk-labs\\.cloud$')
| unique
| list
}}
- name: Display hostnames to create
ansible.builtin.debug: ansible.builtin.debug:
msg: "Services found: {{ service_names }}" msg: "Hostnames found: {{ hostnames }}"
# ── Step 3: Create DNS CNAME records ── # ── Step 3: Create DNS CNAME records ──
- name: Create DNS CNAME record for each service - name: Create DNS CNAME record for each hostname
effectivelywild.technitium_dns.technitium_dns_add_record: effectivelywild.technitium_dns.technitium_dns_add_record:
api_url: "http://{{ dns_server }}.{{ base_domain }}" api_url: "http://{{ dns_server }}.{{ base_domain }}"
api_token: "{{ vault_technitium_api_key }}" api_token: "{{ vault_technitium_api_key }}"
zone: "{{ base_domain }}" zone: "{{ base_domain }}"
name: "{{ item }}.{{ base_domain }}" name: "{{ item }}"
type: "CNAME" type: "CNAME"
cname: "lightning-lane.{{ base_domain }}" cname: "lightning-lane.{{ base_domain }}"
ttl: 360 ttl: 360
validate_certs: false validate_certs: false
loop: "{{ service_names }}" loop: "{{ hostnames }}"
loop_control: loop_control:
label: "{{ item }}.{{ base_domain }}" label: "{{ item }}"