¿Cuál es el equivalente de Puppet's 'a menos que' en Ansible?

9

Antecedentes: en Puppet es posible ejecutar un comando a menos que ya se haya ejecutado:

exec { '/bin/echo root >> /usr/lib/cron/cron.allow':
  path   => '/usr/bin:/usr/sbin:/bin',
  unless => 'grep root /usr/lib/cron/cron.allow 2>/dev/null',
}

Objetivo: ejecutar un comando a menos que ya se haya ejecutado en Ansible

Métodos

tareas / main.yml

- name: add vhost sensu
  command: rabbitmqctl add_vhost /sensu

Resultados

TASK [ansible-rabbitmq : add vhost sensu] **************************************
fatal: [111.222.333.444]: FAILED! => {"changed": true, "cmd": ["rabbitmqctl",
"add_vhost", "/sensu"], "delta": "0:00:00.210140", "end": 
"2016-07-29 12:55:19.384455", "failed": true, "rc": 2, "start":
"2016-07-29 12:55:19.174315", "stderr": "Error: vhost_already_exists: /sensu", 
"stdout": "Creating vhost \"/sensu\" ...", "stdout_lines": 
["Creating vhost \"/sensu\" ..."], "warnings": []}

Discusión

Google unless ansiblemostró este documento sobrewhen . Sobre la base de esa documentación, whense agregó una declaración:

- name: add vhost sensu
  command: rabbitmqctl add_vhost /sensu
  when: rabbitmqctl list_vhosts | grep sensu

ejecutar el código resultó en:

fatal: [192.168.0.9]: FAILED! => {"failed": true, "msg": "The conditional
 check 'rabbitmqctl list_vhosts | grep sensu' failed. The error was: template
 error while templating string: expected token 'end of statement block', got
 'list_vhosts'. String: {% if rabbitmqctl list_vhosts | grep sensu %} True {%
 else %} False {% endif %}\n\nThe error appears to have been in '/etc/ansible
/roles/ansible-rabbitmq/tasks/main.yml': line 10, column 3, but may\nbe
 elsewhere in the file depending on the exact syntax problem.\n\nThe
 offending line appears to be:\n\n\n- name: add vhost sensu\n  ^ here\n"}
  1. En primer lugar, imagine que whenfue exitoso, luego el comando no se ejecutará y luego se verá más como onlyifen Puppet .
  2. En segundo lugar, si el cuándo sería exitoso, ¿debería usarse una marca de escalamiento para simular un a menos?
  3. Usar deregister . ¿Qué pasa si ese archivo se pierde o el vhost ha sido eliminado, por ejemplo, por un humano? Puppet unlesssiempre ejecuta los comandos para que quede claro si el comando debe ejecutarse.
030
fuente

Respuestas:

9

Creo que lo que estás buscando hacer es esto:

- name: get vhosts
  command: rabbitmqctl list_vhosts
  register: vhosts
  changed_when: false

- name: add vhost sensu
  command: rabbitmqctl add_vhost /sensu
  when: "'/sensu' not in vhosts.stdout"

Re: # 3 registerno crea un archivo. Si está capturando la salida de rabbitmqctl list_vhostsvia register, el contenido será tan válido como el estado actual del sistema.

jscott
fuente
3

El problema es la línea when: rabbitmqctl list_vhosts | grep sensu. No es posible usar bash aquí.

Debe colocarlo rabbitmqctl list_vhosts | grep sensuen una tarea separada y registrar el resultado para usarlo en la cláusula when. Puede usar el notfiltro para obtener unlessun comportamiento similar.

Algo como esto debería funcionar:

- name: Get rabbitmq vhosts.
  command: rabbitmqctl list_vhosts | grep sensu
  register: rabbitmq_vhosts

- name: add vhost sensu
  command: rabbitmqctl add_vhost /sensu
  when: not 'sensu' in rabbitmq_vhosts.stdout

En Get rabbitmq vhosts.este ejemplo, siempre se ejecutará. El add vhost sensuúnico si la cadena sensu no está registrada rabbitmq_vhosts.

Consulte la documentación sobre condicionales y filtros jinja para obtener más información.

Henrik Pingel
fuente
El problema persiste:fatal: [IP]: FAILED! => {"changed": true, "cmd": ["rabbitmqctl", "add_vhost", "/sensu"], "delta": "0:00:00.198681", "end": "2016-07-29 13:43:00.870193", "failed": true, "rc": 2, "start": "2016-07-29 13:43:00.671512", "stderr": "Error: vhost_already_exists: /sensu", "stdout": "Creating vhost \"/sensu\" ...", "stdout_lines": ["Creating vhost \"/sensu\" ..."], "warnings": []}
030
hm, probablemente sea mi culpa. Supongo que fue una falta .stdouteditado mi respuesta.
Henrik Pingel
0

La whenopción es lo único que Ansible tiene con respecto a las condiciones. Pero no puede definir directamente un comando allí. whenespera una expresión de Jinja y además se evalúa en el host de control Ansible. Por lo tanto, primero debe ejecutar una tarea para obtener el resultado y registrarlo.

- shell: rabbitmqctl list_vhosts | grep sensu
  register: sensu_vhosts

- name: add vhost sensu
  command: rabbitmqctl add_vhost /sensu
  when: sensu_vhosts.stdout_lines < 1

stdout_lineses una matriz de todas las líneas que devolvió la tarea de shell. Por lo tanto, puede contar el número de entradas y solo ejecutar su tarea cuando se hayan devuelto 0 elementos

udondan
fuente
2
si el / sensu vhost no existe, resulta en:fatal: [IP]: FAILED! => {"changed": true, "cmd": "rabbitmqctl list_vhosts | grep sensu", "delta": "0:00:00.198769", "end": "2016-07-29 13:45:59.069981", "failed": true, "rc": 1, "start": "2016-07-29 13:45:58.871212", "stderr": "", "stdout": "", "stdout_lines": [], "warnings": []}
030