refactor: simplificar naming de nodos con auto-deducción #80

Merged
Numerica merged 26 commits from refactor-simplify-node-naming into master 2025-12-22 20:30:40 +00:00
22 changed files with 94 additions and 77 deletions

View File

@ -60,6 +60,7 @@ matrix:
- kaasavi
- llavero
- deabajo
- testnet
- service_name: respaldos
domains:
@ -67,11 +68,9 @@ matrix:
nodo: respaldos.comun
force_https: yes
- service_name: marmite
domains:
- marmite.abyaya.la
nodo: marmite.comun
- nodo: marmite
force_https: yes
# Auto-deduced: domains: [marmite.abyaya.la], rap_dn: marmite.comun
- service_name: yanapak
domains:

View File

@ -1,3 +1,6 @@
host_ip: 5.161.236.18
main_zone: abyaya.la
vpn_name: comun
vpn_proxy: 10.13.12.1
proxy_scale: 2
domains_default_force_https: yes

View File

@ -1 +1,5 @@
host_ip: 157.180.114.62
main_zone: abyayala.red
vpn_name: comun
vpn_proxy: 10.13.12.159
proxy_scale: 1

View File

@ -1,9 +1,10 @@
- set_fact:
current_service: "{{ item }}"
service_name: "{{ item.service_name }}"
# Deducir service_name: usar 'nodo' si existe, sino 'service_name' (retrocompatibilidad)
service_name: "{{ item.nodo | default(item.service_name) }}"
Review

acabo de entender que lo que vos haces con set_fact yo lo hago en el inventario :P

acabo de entender que lo que vos haces con `set_fact` yo lo hago en el inventario :P
service_roles: "{{ item.roles | default([]) }}"
- include_role:
- include_role:
name: "{{ current_role_name }}"
with_items: "{{ service_roles }}"
loop_control:

View File

@ -2,12 +2,14 @@
apt:
name: dnsmasq
state: present
- name: configuracion de red comun
template:
src: dnsmasq.conf
dest: "/etc/dnsmasq.conf"
notify:
- restart dnsmasq
- name: activar el servicio
systemd_service:
name: dnsmasq

View File

@ -74,8 +74,8 @@ resolv-file=/etc/resolv.local
# Add local-only domains here, queries in these domains are answered
# from /etc/hosts or DHCP only.
local=/comun/
domain=comun
local=/{{ vpn_name }}/
domain={{ vpn_name }}
# Add domains which you want to force to an IP address here.
# The example below send any host in double-click.net to a local
@ -117,12 +117,12 @@ domain=comun
# specified interfaces (and the loopback) give the name of the
# interface (eg eth0) here.
# Repeat the line for more than one interface.
interface=comun
interface={{ vpn_name }}
# Or you can specify which interface _not_ to listen on
except-interface=eth0
# Or which to listen on by address (remember to include 127.0.0.1 if
# you use this.)
listen-address=10.13.12.1,127.0.0.1
listen-address={{ vpn_proxy }},127.0.0.1
# If you want dnsmasq to provide only DNS service on an interface,
# configure it as shown above, and then use the following line to
# disable DHCP and TFTP on it.

View File

@ -6,7 +6,7 @@
-A INPUT -m conntrack --ctstate INVALID -j DROP
-A INPUT -p icmp -m icmp --icmp-type 8 -m conntrack --ctstate NEW -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -i comun -j ACCEPT
-A INPUT -i {{ vpn_name }} -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p udp -m udp --dport 53 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 53 -j ACCEPT

View File

@ -5,6 +5,6 @@ server {
client_max_body_size 4k;
location / {
proxy_pass http://10.13.12.1:3000;
proxy_pass http://{{ vpn_proxy }}:3000;
}
}

View File

@ -1,10 +1,10 @@
- set_fact:
is_abyayala_subdomain: "{{ domain.endswith('.abyaya.la') }}"
is_abyayala_subdomain: "{{ domain.endswith('.' ~ main_zone) }}"
- name: extract zone and hostname for abyaya.la subdomains
- name: extract zone and hostname for main zone subdomains
set_fact:
zone: "abyaya.la."
hostname: "{{ domain | regex_replace('([a-z0-9-]+)\\.abyaya\\.la', '\\1') }}"
zone: "{{ main_zone ~ '.' }}"
hostname: "{{ domain | regex_replace('([a-z0-9-]+)\\.' ~ main_zone|regex_escape , '\\1') }}"
when: is_abyayala_subdomain
- name: split domain into parts
@ -30,6 +30,11 @@
hostname: "{{ domain_parts[:-2] | join('.') if domain_parts | length > 2 else '@' }}"
when: not is_abyayala_subdomain and not uses_compound_tld
- name: Debug knsupdate for this domain
debug:
msg: "{{ lookup('template', 'templates/commands.j2') }}"
when: is_abyayala_subdomain
- name: knsupdate for this domain
shell: knsupdate
args:

View File

@ -10,14 +10,18 @@
include_role: name=certbot
tags: certbot
- name: set main_zone_regex from main_zone
set_fact:
main_zone_regex: "{{ '.' ~ main_zone | replace('.', '\\.') }}"
- name: configuration paths
file: path={{ comun }} state=directory
file: path={{ abc }} state=directory
with_items:
- "{{ stream_path }}"
- "{{ conf_path }}"
- "{{ certbot_webroot }}"
loop_control:
loop_var: comun
loop_var: abc
- name: virtual hosts path
file: path={{ vhosts_path }} state=directory
@ -37,34 +41,15 @@
loop_control:
loop_var: common
- name: domains' stuff
- name: neo stuff
block:
- name: slice matrix with those having domains defined
set_fact:
matrix_loop: "{{ matrix_loop | default([]) | union([ domino ]) }}"
with_items: "{{ matrix }}"
when: "{{ domino.domains is defined and domino.nodo is defined }}"
- name: normalize and build matrix_loop
Review

domino es un typo que se arrastró por autocompletado?

`domino` es un typo que se arrastró por autocompletado?
Review

no. es mi manía de ponerles nombres no-standard a las variables para diferenciarlas mejor
podriamos estandarizarlas todas

no. es mi manía de ponerles nombres no-standard a las variables para diferenciarlas mejor podriamos estandarizarlas todas
include_tasks: normalize_node.yml
with_items: "{{ matrix }}"
when: "{{ (domino.domains is defined or domino.nodo is defined or domino.service_name is defined) }}"
loop_control:
loop_var: domino
- name: ensure abyaya.la subdomain is always first in domains list
set_fact:
matrix_loop_with_defaults: "{{ matrix_loop_with_defaults | default([]) | union([ item_with_default ]) }}"
vars:
existing_abyayala_domains: "{{ item.domains | select('match', '.*\\.abyaya\\.la$') | list }}"
has_abyayala_domain: "{{ existing_abyayala_domains | length > 0 }}"
default_domain: "{{ item.service_name }}.abyaya.la"
other_domains: "{{ item.domains | reject('match', '.*\\.abyaya\\.la$') | list }}"
abyayala_domain_to_use: "{{ existing_abyayala_domains[0] if has_abyayala_domain else default_domain }}"
domains_with_default: "{{ [abyayala_domain_to_use] + other_domains }}"
item_with_default: "{{ item | combine({'domains': domains_with_default}) }}"
with_items: "{{ matrix_loop | default([]) }}"
- name: update matrix_loop with defaults
set_fact:
matrix_loop: "{{ matrix_loop_with_defaults }}"
when: matrix_loop_with_defaults is defined
- name: certificates loop
include_tasks: ../../certbot/tasks/certbot.yml
with_items: "{{ matrix_loop | default([]) }}"
@ -78,7 +63,7 @@
with_items: "{{ matrix_loop }}"
loop_control:
loop_var: vhost
when: (service is undefined) or (service is defined and service == vhost.service_name)
when: ((service is undefined) or (service is defined and service == vhost.service_name)) and not vhost.skip_vhost
- name: streams loop
include_tasks: stream.yml

View File

@ -0,0 +1,21 @@
- set_fact:
_existing_abyayala_domains: "{{ (domino.domains | default([])) | select('match', '.*' ~ main_zone_regex ~ '$') | list }}"
_other_domains: "{{ (domino.domains | default([])) | reject('match', '.*' ~ main_zone_regex ~ '$') | list }}"
_node_name: "{{ domino.nodo | default(domino.service_name) }}"
_default_domain: "{{ (domino.nodo | default(domino.service_name)) ~ '.' ~ main_zone }}"
_default_rap_dn: "{{ (domino.nodo | default(domino.service_name)) ~ '.' ~ vpn_name }}"
Outdated
Review

eventualmente haría que abyaya.la y comun sean variables

eventualmente haría que `abyaya.la` y `comun` sean variables
fauno marked this conversation as resolved Outdated
Outdated
Review

nunca entendí por qué https es opcional

nunca entendí por qué https es opcional

hay servicios que les jodés si les forzás https, como Icecast, donde los clientes de streaming en general no soportan https

hay servicios que les jodés si les forzás https, como Icecast, donde los clientes de streaming en general no soportan https
- set_fact:
domino_normalized:
nodo: "{{ _node_name }}"
rap_dn: "{{ domino.rap_dn | default(_default_rap_dn) }}"
domains: "{{ [(_existing_abyayala_domains[0] if (_existing_abyayala_domains | length > 0) else _default_domain)] + _other_domains }}"
force_https: "{{ domino.force_https | default(domains_default_force_https) }}"
ports: "{{ domino.ports | default([]) }}"
enable_compression: "{{ domino.enable_compression | default(domains_default_enable_compression) }}"
roles: "{{ domino.roles | default([]) }}"
service_name: "{{ domino.service_name | default(_node_name) }}"
skip_vhost: "{{ (domino.roles is defined and (domino.roles | length > 0) and domino.domains is not defined) }}"
- set_fact:
matrix_loop: "{{ matrix_loop | default([]) | union([ domino_normalized ]) }}"

View File

@ -1,10 +1,10 @@
- set_fact:
vhost_dest: "{{ stream_path }}/{{ vhost.domains[0] }}.conf"
vhost_dest: "{{ stream_path }}/{{ vhost.service_name }}.conf"
- name: default stream for ssh
template:
src: "{{ default_stream }}"
dest: "{{ vhost_dest }}"
when: vhost.ports is defined
when: vhost.ports is defined and (vhost.ports | length > 0)
notify:
- reload proxy

View File

@ -1,12 +1,12 @@
- set_fact:
vhost_dest: "{{ vhosts_path }}/{{ vhost.domains[0] }}.conf"
- block:
- block:
- set_fact:
custom_vhost: "roles/{{ vhost.roles[0] }}/templates/vhost.conf"
- set_fact:
proxy_conf: "roles/{{ vhost.roles[0] }}/templates/proxy.conf"
when: vhost.roles is defined
when: vhost.roles is defined and (vhost.roles | length > 0)
- set_fact:
proxy_conf_look: "{{ lookup('template', proxy_conf) }}"
@ -16,7 +16,7 @@
template:
src: "{{ default_vhost }}"
dest: "{{ vhost_dest }}"
when: (vhost.roles is undefined or vhost.roles[0] == 'proxy') or (custom_vhost is undefined or custom_vhost is not is_file)
when: (vhost.roles is undefined or (vhost.roles | length == 0) or vhost.roles[0] == 'proxy') or (custom_vhost is undefined or custom_vhost is not is_file)
notify:
- reload proxy
@ -24,6 +24,6 @@
template:
src: "{{ custom_vhost }}"
dest: "{{ vhost_dest }}"
when: (vhost.roles is defined and vhost.roles[0] != 'proxy') and custom_vhost is defined and custom_vhost is is_file
when: (vhost.roles is defined and (vhost.roles | length > 0) and vhost.roles[0] != 'proxy') and custom_vhost is defined and custom_vhost is is_file
notify:
- reload proxy

View File

@ -19,7 +19,7 @@
proxy_ssl_server_name on;
proxy_ssl_name $ssl_server_name;
proxy_pass https://$comun_{{ vhost.nodo | replace(".", "") }};
proxy_pass https://$comun_{{ vhost.rap_dn | replace(".", "") }};
Review

por que estabamos haciendo este replace? no puede ser otra variable con el nombre sanitizado para nginx asi no lo tenemos que repetir todo el rato?

por que estabamos haciendo este replace? no puede ser otra variable con el nombre sanitizado para nginx asi no lo tenemos que repetir todo el rato?
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;

View File

@ -1,15 +1,11 @@
upstream ssh_{{ vhost.nodo | replace(".", "") }} {
server {{ vhost.nodo }}:22;
upstream ssh_{{ vhost.rap_dn | replace(".", "") }} {
server {{ vhost.rap_dn }}:22;
}
server {
listen {{ vhost.ports[0] }};
{% if vhost.root | default(false) %}
server_name {{ vhost.domains | join(' ') }};
{% else %}
server_name .{{ vhost.domains | join(' .') }};
{% endif %}
server_name {{ vhost.service_name }}.{{ main_zone }};
proxy_pass ssh_{{ vhost.nodo | replace(".", "") }};
proxy_pass ssh_{{ vhost.rap_dn | replace(".", "") }};
}

View File

@ -1,10 +1,10 @@
map $http_host $comun_{{ vhost.nodo | replace(".", "") }} {
map $http_host $comun_{{ vhost.rap_dn | replace(".", "") }} {
hostnames;
{% for domain in vhost.domains %}
{% if vhost.root | default(false) %}
{{ domain }} {{ vhost.nodo }};
{{ domain }} {{ vhost.rap_dn }};
{% else %}
.{{ domain }} {{ vhost.nodo }};
.{{ domain }} {{ vhost.rap_dn }};
{% endif %}
{% endfor %}
}
@ -18,7 +18,7 @@ server {
listen 80;
resolver 10.13.12.1 valid=300s;
resolver {{ vpn_proxy }} valid=300s;
resolver_timeout 5s;
{% if vhost.root | default(false) %}

View File

@ -1,5 +1,6 @@
domains_default_ssl: no
domains_default_force_https: no
domains_default_enable_compression: no
# nginx
vhosts_path: "{{ compose_path }}/proxy/vhosts"

View File

@ -2,7 +2,7 @@
# https://serverfault.com/questions/1108989/isc-dhcp-client-dhclient-alternative
- name: instalar dependecias de la RAP
apt:
name: ['tinc', 'rsync', 'dhcp5']
name: ['tinc', 'rsync', 'dhcpcd5']
state: latest
# update_cache: yes
tags: installation
@ -11,13 +11,13 @@
- name: copiar el codigo fuente
synchronize:
src: ../roles/rap/code/rap
src: ../roles/rap/code/rap/
dest: "{{ rap_path }}"
perms: true
- name: hacer ejecutable el archivo rap
file:
path: "{{ rap_path }}/rap/rap"
path: "{{ rap_path }}/rap"
state: touch
mode: '774'
modification_time: preserve
@ -26,13 +26,13 @@
- name: inicializar el nodo
shell:
cmd: "./rap init -i {{ nodo }}"
chdir: "{{ rap_path }}/rap"
chdir: "{{ rap_path }}"
environment:
NETWORK: comun
NETWORK: "{{ vpn_name }}"
- name: instalar el nodo
shell:
cmd: "./rap install -v {{ nodo }}"
chdir: "{{ rap_path }}/rap"
chdir: "{{ rap_path }}"
environment:
NETWORK: comun
NETWORK: "{{ vpn_name }}"

View File

@ -24,9 +24,9 @@
cmd: "./rap add-host {{ althost }} {{ nod }}"
chdir: "{{ rap_path }}"
args:
creates: "{{ rap_path }}/networks/comun/abyayala/hosts/{{ nod }}"
creates: "{{ rap_path }}/networks/{{ vpn_name }}/abyayala/hosts/{{ nod }}"
environment:
NETWORK: comun
NETWORK: "{{ vpn_name }}"
with_items: "{{ item.nodos }}"
loop_control:
loop_var: nod
@ -36,4 +36,4 @@
cmd: "./rap install -v {{ althost }}"
chdir: "{{ rap_path }}"
environment:
NETWORK: comun
NETWORK: "{{ vpn_name }}"

View File

@ -1,5 +1,6 @@
# Instalacion de la RAP en maquina local
# ansible-playbook --become tasks/rap.yml -e "host=localhost nodo=chem" -i hosts.local
# ansible-playbook tasks/rap.yml -e "host=testing nodo=testnet"
---
- hosts: "{{ host }}"
tasks:

View File

@ -16,8 +16,7 @@ matrix:
nodos:
- qi
- service_name: qi
domains:
- qi.abyayala.red
nodo: qi.comun
- nodo: qi
ports:
- 531
# force_https: yes