Ansible comprueba si la variable existe en la lista de atributos

Ansible comprueba si la variable existe en la lista de atributos

Tengo una variable que contiene detalles de las máquinas host en mi red (llamada 'hostlist'; creo que a esto se le llama diccionario, pero no estoy seguro de la terminología. La variable está definida en un archivo en group_vars/all, por lo que es disponible en todos los libros de jugadas (no estoy seguro si esto es importante).

Tengo una obra que me gustaría ejecutar solo si ansible_hostname no se encuentra en la lista de nombres de host en hostlist. Los nombres de host en hostlist son uno de los atributos de la variable, pero nuevamente no estoy seguro de si "atributo" es el término correcto...

La lista de hosts se define como:

hostlist:
  - { name: 'host1', ip_addr: '192.168.2.31', hostgrp: 'physical_workstation' }
  - { name: 'host2', ip_addr: '192.168.2.32', hostgrp: 'physical_workstation' }
  - { name: 'host3', ip_addr: '192.168.2.33', hostgrp: 'virtual_machine' }

La jugada que estoy usando para intentar que esto funcione es:

- name: Conditional test
  debug:
    msg: "ansible_hostname not found in hostlist."
  when: ansible_hostname not in hostlist.name

No estoy seguro de la sintaxis requerida en la condición o si lo que quiero se puede lograr de esta manera.

Respuesta1

Probablemente hay formas más elegantes de hacerlo, pero algo como esto funciona para mí:

Si su archivo de inventario se ve así

host1
host2
host3
host4

Entonces, un libro de jugadas con el siguiente contenido solo se ejecutará host4porque no coincide en la var de la lista de hosts:
$ cat test.yml

- hosts: all
  vars:
    hostlist:
      - { name: 'host1', ip_addr: '192.168.2.31', hostgrp: 'physical_workstation' }
      - { name: 'host2', ip_addr: '192.168.2.32', hostgrp: 'physical_workstation' }
      - { name: 'host3', ip_addr: '192.168.2.33', hostgrp: 'virtual_machine' }
  tasks:

    - name: Conditional test
      debug:
        msg: "ansible_hostname not found in hostlist."
      when: hostlist|selectattr("name", "equalto", ansible_hostname)|list|length == 0

cuando se llama así:

ansible-playbook test.yml

significa que solo host4 ejecuta el bloque de tareas....

PLAY [all] *************************************************

TASK [Gathering Facts] *************************************
ok: [host1]
ok: [host2]
ok: [host3]
ok: [host4]

TASK [debug] ***********************************************
ok: [host4] => {
    "msg": "hostname not in hostlist name list"
}
skipping: [host1]
skipping: [host2]
skipping: [host3]

Respuesta2

Opcionalmente, esta condición es más limpia.

    when: inventory_hostname not in hostlist|map(attribute="name")|list

Úselo inventory_hostnameen lugar de ansible_hostnamesi desea comparar con la lista de alias del inventario. Ver¿Cuál es la diferencia entre inventario_hostname y ansible_hostname?.

Respuesta3

una solución alternativa es (como se sugiere en el comentario sobre la pregunta) refactorizar la lista de hosts en el inventario de esta manera:

[physical_workstation]
host1 ansible_host=192.168.2.31
host2 ansible_host=192.168.2.32

[virtual_machine]
host3 ansible_host=192.168.2.33

[all]
host4 ansible_host=192.168.2.34

Luego puedes simplificar el libro de jugadas para ejecutar jugadas contra anfitriones que no están en ningún grupo, usando el ungroupedgrupo especial, que selecciona anfitriones allque no están en ningún otro grupo:

- hosts: ungrouped
  tasks:
    - name: only ungrouped
      debug:
        msg: "host not found in any other group."

o ejecutar cosas contra esos hosts específicos en grupos...

- hosts: physical_workstation:virtual_machine
  tasks:
    - name: only in specified groups
      debug:
        msg: |
          This will run on machines that are in groups:
          physical_workstation or virtual_machine

salidas

PLAY [ungrouped] ***********************************************

TASK [only ungrouped] ******************************************
ok: [host4] => {
    "msg": "host not found in any other group."
}

PLAY [physical_workstation:virtual_machine] ********************

TASK [only in specified groups] ********************************
ok: [host1] => {
    "msg": "This will run on machines that are in groups:\nphysical_workstation or virtual_machine"
}
ok: [host2] => {
    "msg": "This will run on machines that are in groups:\nphysical_workstation or virtual_machine"
}
ok: [host3] => {
    "msg": "This will run on machines that are in groups:\nphysical_workstation or virtual_machine"
}

información relacionada