Controlar tareas con condiciones y bucles

AnsibleBeginner
Practicar Ahora

Introducción

Un playbook puede seleccionar trabajos distintos para cada host sin duplicar toda la lista de tareas. Combinarás entradas booleanas de políticas con datos recopilados del sistema operativo, procesarás cada elemento de una lista estructurada y usarás resultados reales registrados de inspección para una decisión independiente de aprobación. Los archivos reales y la limpieza explícita harán observable tanto el comportamiento seleccionado como el omitido.

Seleccionar tareas con entradas booleanas y datos recopilados

En este paso, harás que un playbook reutilizable actúe de forma distinta en los dos hosts y elimine explícitamente las salidas cuando se desactive la política.

El entorno preparado tiene una entrada de aprobación separada en /home/automation/maintenance-approved únicamente en web1. Deja esa entrada sin cambios por ahora; la primera decisión de política usa en su lugar una variable booleana y datos descubiertos del sistema operativo.

Entra en el proyecto del controlador:

cd /home/labex/project

Los archivos de variables de host asocian datos con cada nombre del inventario. Escribe valores booleanos YAML sin comillas para que sigan siendo valores true/false en lugar de cadenas:

cat > host_vars/web1.yml <<'YAML'
maintenance_enabled: true
YAML
cat > host_vars/web2.yml <<'YAML'
maintenance_enabled: false
YAML

La palabra clave when evalúa una expresión booleana para el host actual. No encierres la expresión entre llaves Jinja. Aquí and exige tanto una política activada como datos de la familia Debian. not invierte un booleano y or permite que cualquiera de las dos razones seleccione la rama de limpieza.

cat > maintenance.yml <<'YAML'
- name: Apply a host-specific maintenance policy
  hosts: all
  gather_facts: true
  tasks:
    - name: Prepare the common policy directory
      ansible.builtin.file:
        path: /home/automation/maintenance-policy
        state: directory
        mode: "0750"

    - name: Record enabled Debian maintenance
      ansible.builtin.copy:
        dest: /home/automation/maintenance-policy/enabled.txt
        content: "Enabled maintenance\n"
        mode: "0640"
      when: maintenance_enabled and ansible_facts.os_family == "Debian"

    - name: Remove the marker when the policy is disabled
      ansible.builtin.file:
        path: /home/automation/maintenance-policy/enabled.txt
        state: absent
      when: not maintenance_enabled or ansible_facts.os_family != "Debian"
YAML

El directorio común existe en ambos hosts. Solo los hosts Debian con la política activada reciben el marcador; la tarea absent complementaria lo elimina cuando se desactiva la política. Una tarea de creación omitida por sí sola dejaría un marcador antiguo, por lo que la limpieza es una tarea separada de estado deseado.

Valida y aplica la política:

ansible-playbook maintenance.yml --syntax-check
ansible-playbook maintenance.yml

La salida debería mostrar decisiones distintas de changed/ok/skipped para web1 y web2. Inspecciona los metadatos reales del marcador en ambos hosts:

ansible all -m ansible.builtin.stat -a 'path=/home/automation/maintenance-policy/enabled.txt'

Stat debería informar exists true en web1 y false en web2. Para ejercitar la limpieza, sobrescribe el booleano para ambos hosts. Las variables extra JSON conservan el tipo booleano false; las comillas simples exteriores protegen el JSON de la interpretación de la shell:

ansible-playbook maintenance.yml -e '{"maintenance_enabled":false}'
ansible all -m ansible.builtin.stat -a 'path=/home/automation/maintenance-policy/enabled.txt'

Ambos marcadores deberían estar ahora ausentes. Restablece la política guardada de cada host ejecutando sin el valor temporal que la sobrescribe:

ansible-playbook maintenance.yml

Web1 debería recuperar el marcador mientras web2 permanece desactivado. El valor temporal no editó los archivos guardados de variables de host.

Aplicar cada elemento de un bucle estructurado

En este paso, producirás un registro real de comprobación de mantenimiento para cada elemento declarado en el host con la política activada.

Una lista YAML contiene varias entradas introducidas con un guion. Cada entrada siguiente es un mapa con campos name y purpose. Las variables de grupo para all hacen que esta lista esté disponible para ambos hosts, mientras que la condición booleana existente sigue decidiendo qué host recibe salidas.

cat > group_vars/all.yml <<'YAML'
maintenance_checks:
  - name: disk
    purpose: Inspect disk space
  - name: logs
    purpose: Inspect application logs
  - name: packages
    purpose: Inspect package state
YAML

loop repite una tarea para cada entrada de la lista. Dentro de una iteración, item.name e item.purpose leen los campos de esa entrada. La condición when se evalúa para cada host y elemento. Añade estas tareas al playbook existente, manteniendo la sangría alineada con las tareas anteriores:

cat >> maintenance.yml <<'YAML'

    - name: Prepare checks only for enabled Debian hosts
      ansible.builtin.file:
        path: /home/automation/maintenance-policy/checks
        state: directory
        mode: "0750"
      when: maintenance_enabled and ansible_facts.os_family == "Debian"

    - name: Write every declared maintenance check
      ansible.builtin.copy:
        dest: "/home/automation/maintenance-policy/checks/{{ item.name }}.txt"
        content: |
          host={{ inventory_hostname }}
          check={{ item.name }}
          purpose={{ item.purpose }}
        mode: "0640"
      loop: "{{ maintenance_checks }}"
      when: maintenance_enabled and ansible_facts.os_family == "Debian"

    - name: Remove check outputs when the policy is disabled
      ansible.builtin.file:
        path: /home/automation/maintenance-policy/checks
        state: absent
      when: not maintenance_enabled or ansible_facts.os_family != "Debian"
YAML

La tarea de limpieza elimina todo el directorio de comprobaciones en los hosts desactivados, incluidas las salidas antiguas de una política activada anteriormente. El bucle escribe contenido estable y permisos explícitos en los hosts activados.

Aplica el playbook ampliado:

ansible-playbook maintenance.yml

Web1 debería tener tres resultados del bucle, uno por comprobación. Web2 debería omitir esas escrituras y no conservar ningún directorio checks. Lee los tres artefactos reales de web1 en lugar de considerar un elemento correcto como prueba de toda la lista:

ansible web1 -m ansible.builtin.command -a 'cat /home/automation/maintenance-policy/checks/disk.txt /home/automation/maintenance-policy/checks/logs.txt /home/automation/maintenance-policy/checks/packages.txt'

La salida debería identificar host=web1 para cada registro y mostrar el nombre y propósito de comprobación correspondientes. Inspecciona el host desactivado de forma independiente:

ansible web2 -m ansible.builtin.stat -a 'path=/home/automation/maintenance-policy/checks'

Su resultado stat debería informar exists false. Estos registros declaran instrucciones de comprobación de mantenimiento; no pretenden ejecutar por sí mismos las inspecciones de disco, registros o paquetes.

Crear ramas según un resultado registrado de inspección

En este paso, usarás un resultado real de stat como entrada independiente de decisión y confirmarás que la política completa es estable al repetirla.

La entrada de aprobación es independiente de maintenance_enabled. Una tarea stat siempre inspecciona cada host y después register guarda el resultado de ese host. Su booleano stat.exists distingue de forma segura una entrada existente de una ruta ausente. Añade la inspección y las tareas complementarias de salida:

cat >> maintenance.yml <<'YAML'

    - name: Inspect the independent approval input
      ansible.builtin.stat:
        path: /home/automation/maintenance-approved
      register: approval_info

    - name: Record an existing approval input
      ansible.builtin.copy:
        dest: /home/automation/maintenance-policy/approved.txt
        content: "Approval input exists\n"
        mode: "0640"
      when: approval_info.stat.exists

    - name: Remove the output when approval input is absent
      ansible.builtin.file:
        path: /home/automation/maintenance-policy/approved.txt
        state: absent
      when: not approval_info.stat.exists
YAML

La tarea copy consume el valor exists registrado. La tarea absent cubre su opuesto para que eliminar una entrada de aprobación también elimine la salida de aprobación obsoleta. Esta rama se basa en el estado inspeccionado en lugar de un mensaje debug fijo.

Ejecuta la política completa:

ansible-playbook maintenance.yml

La entrada preparada de aprobación existe únicamente en web1, por lo que solo web1 debería tener approved.txt. Inspecciona ambas rutas reales de salida:

ansible all -m ansible.builtin.stat -a 'path=/home/automation/maintenance-policy/approved.txt'

Web1 debería informar exists true y web2 false. Repite el playbook:

ansible-playbook maintenance.yml

Ambas filas del resumen deberían informar changed=0, failed=0 y unreachable=0. Las tareas omitidas son esperadas cuando una condición es falsa; cada elemento requerido del bucle y cada salida seleccionada deben seguir existiendo con el contenido correcto.

Resumen

Has usado datos booleanos por host y datos descubiertos para seleccionar tareas, procesado cada mapa de un bucle y creado ramas según metadatos de stat registrados. Las tareas absent complementarias eliminaron salidas obsoletas en lugar de suponer que una creación omitida deshace el estado anterior. Ambos hosts convergieron a los resultados distintos de sus políticas sin cambios repetidos innecesarios.