
Ansible no es un lenguaje de programación.
Tal vez esta información no sea nueva para ti, o tal vez nunca pensaste en ello. Ansible funciona muy bien, entonces, ¿qué importa si es un lenguaje de programación?
Empecé como programador (hace mucho tiempo, en una galaxia muy, muy lejana…) pero mi primera exposición fue Microsoft BASIC, luego COBOLCICS y PerlHe usado otros lenguajes menos antiguos o raros como Java, Python, JavaScript, etc. No digo que sea competente en todos ellos, pero siempre trato de aprender cómo hacer las cosas en los idiomas más recientes y emocionantes.
Recientemente, esto le sucedió a Ansible, aunque Ansible es no un lenguaje de programación.
Ansible no es un lenguaje
Si Ansible no es un lenguaje de programación, ¿qué es?
Ansible es una herramienta escrita en Python que utiliza el lenguaje de marcado declarativo YAML para describir los estados de configuración y dispositivos deseados.
Vinculado al concepto de «estado deseado», Ansible también utiliza idempotenciaAspectos que declara que están configurados en el dispositivo de destino, por ejemplo, el archivo o directorio existe, el paquete está instalado, el servicio se está ejecutando, etc. Cuando hace esto, puede ejecutar su libro de jugadas de Ansible varias veces sin «romper» el objetivo. La mayoría de los módulos de Ansible saben lo que se debe hacer y solo informan que se han realizado cambios en el estado del recurso cuando se requieren cambios.
[ Get started with IT automation with the Ansible Automation Platform beginner’s guide. ]
Esta es mi opinión sobre lo que necesita saber al programar con Ansible.
1. Condiciones
La forma más fácil de definir si una tarea se ejecutará en Ansible es usar when
Estado de salud. Puede encontrar muchos ejemplos en la documentación de Ansible, pero aquí hay uno que muestra algunos aspectos interesantes:
---
- name: When
hosts: localhost
gather_facts: False
vars:
my_number: "1138"
my_string: "AA-589"
tasks:
- name: A - The Force is strong with this one
ansible.builtin.debug:
msg: "Use the Force, Luke"
when:
- (my_number | int) == 1138
- my_string == 'AA-589'
- name: B - Others
ansible.builtin.debug:
msg: "Do other things"
when: (my_number | int) != 1138 or (my_string != 'AA-589')
En la primera tarea usé la siguiente lista de condiciones when
lo que significa una lógica yAdemás, tenga en cuenta que coacciono el tipo de var my_number
para ser un número entero (en este caso, necesito hacer esto porque necesito proporcionar la variable a través de algún otro método).
En la segunda tarea, la condición está en una línea porque uso lógica oEn mi ejemplo, esta combinación niega la condición de la primera tarea.
Cuando se ejecuta el libro de jugadas, se ejecuta la primera tarea y se omite la segunda tarea.
Pero la primera tarea se omite y la segunda tarea se ejecuta cuando ejecuta el libro de jugadas pasando un valor diferente para al menos una variable:
$ ansible-playbook 01_when.yml -e my_number=5150 -e my_string="Other rebel"
2. Proceso de ejecución
Hay algunos aspectos especiales cuando observa el orden en que se ejecutan las cosas en Ansible.
En un libro de jugadas simple, las secuencias de tareas se ejecutan en el orden en que aparecen.si llamas roles
En el nivel del juego, como se muestra en el siguiente ejemplo, el personaje ejecuta delantero La primera tarea:
---
- name: Simple play
hosts: webservers
roles:
- common
- webservers
tasks:
- name: Task 01
(...)
...
manipulador es otro caso especial. El ejemplo provisto en la documentación oficial de Ansible se ve así:
---
- name: Verify apache installation
hosts: webservers
vars:
http_port: 80
max_clients: 200
remote_user: root
tasks:
- name: Ensure Apache httpd is the latest version
ansible.builtin.yum:
name: httpd
state: latest
- name: Write httpd config file
ansible.builtin.template:
src: /srv/httpd.j2
dest: /etc/httpd.conf
notify:
- Restart apache
- name: Ensure httpd is running
ansible.builtin.service:
name: httpd
state: started
handlers:
- name: Restart httpd
ansible.builtin.service:
name: httpd
state: restarted
...
en la tarea Write httpd config file
Este notify
cláusula apunta a una tarea de controlador denominada Restart httpd
Se ejecuta la acción del controlador. a no ser que Esta tarea conduce a cambió estado. El servicio se reinicia después de que se completa el cambio.
en el interior handlers
sección, nombre de la tarea Restart httpd
Se ejecuta cuando cambia la tarea que apunta a ella.
En este escenario simple, el controlador se ejecuta en último lugar, si lo hay.
Más concretamente, según documento, cuando usa la opción de roles en el nivel de juego, Ansible trata los roles como importaciones estáticas y los procesa durante la resolución del libro de jugadas. Ansible ejecuta cada jugada en el siguiente orden:
- ningún
pre_tasks
definido en la obra - cualquier controlador desencadenado por
pre_tasks
- cada rol enumerado en roles, en el orden indicado; cualquier dependencia de rol definida en roles
meta/main.yml
Ejecutar primero (sujeto a filtrado de etiquetas y condiciones) - Cualquier misión definida en la obra.
- Cualquier controlador desencadenado por roles o tareas
- ningún
post_tasks
definido en la obra - cualquier controlador desencadenado por
post_tasks
Así que si una obra tiene pre_tasks
O roles con handlers, lo que afecta el orden en que se realizan las operaciones, por lo que es importante prestar atención al orden ya que no es lineal.
Mi opción es usar import_roles o include_roles En lugar de usar este método junto con personajes de nivel de juego (a menos que mi libro de jugadas principal tenga si solo Personajes a nivel de juego, eso es todo).
[ Want to test your sysadmin skills? Take a skills assessment today. ]
La documentación describe diferencia entre import
y include
La idea básica es import*
Al analizar un libro de jugadas, las declaraciones son estáticas (preprocesadas), mientras que include*
Las declaraciones son dinámicas.Afecta el comportamiento humano. loops
, when
condiciones y otros aspectos, pero estos están más allá del alcance de este artículo.
3. si/entonces/si no
El ejemplo anterior implicó when
es una declaración si/entonces, pero a nivel de tarea.Si desea utilizar un sencillo if
Asigne variables o llame a diferentes condiciones lookup
(o algo más para decidir)?
Bueno, a veces puedes usar Santuario 2 expresiones para ayudar a resolver este problema.
---
- name: Jinja2 IF
hosts: localhost
vars:
change_provided: True
job_name: death_star
change_string: destroy
current_date_time: 1977-01-01
tasks:
- name: Set base schedule name
ansible.builtin.set_fact:
base_schedule_name: "{%- if (change_provided | bool) -%}
{{ job_name }}_{{ change_string }}
{%- else -%}
{{ job_name }}_{{ current_date_time }}
{%- endif -%}"
- name: Show value
ansible.builtin.debug:
msg: "{{ base_schedule_name }}"
...
En el libro de jugadas anterior, tengo variables estáticamente definidas para demostrar if
en código Jinja2. Estas variables pueden provenir de algunos cálculos u otros procesos en la vida real.
[ Download now: Advanced Linux commands cheat sheet. ]
Esto es lo que sucede cuando uso set_fact
asignar a base_schedule_name
:
- Este
{%
y%}
es el delimitador que indica el código Jinja2.En este caso, hay más-
El marcado le indica a Jinja2 que quiero eliminar el carácter de espacio antes de la variable (los espacios son solo por estética). - si
change_provided
Es cierto que combinojob_name
subrayado ychange_string
.Solo se asigna este contenido, y se omiten los espacios antes y después de la variable, porque la he usado antes{%-
y-%}
. - Este
else
Las declaraciones son similares a lo que podría saber de otros idiomas.En este caso combinojob_name
subrayado ycurrent_date_time
. - Al final,
endif
cierreif
.
Como puede ver, esto es un poco peligroso y puede ensuciarse. Usa el buen sentido común.
puede usar solo uno when
Una condición para hacer lo mismo en una tarea. Sin embargo, Jinja2 también se puede usar para manejar una lógica relativamente más compleja, como manejar bucles, calcular y filtrar elementos en listas, etc. Esto corre el riesgo de complicar demasiado las cosas.
Al igual que con cualquier lenguaje de programación real, use algo que facilite la implementación, el mantenimiento, la solución de problemas y la comprensión.
4. Ejecutar un proceso en el sistema operativo
Al comienzo de este artículo mencioné la idea de idempotencia. Siempre que sea posible, trate de usar módulos de Ansible para realizar operaciones, ya que contiene la siguiente lógica necesaria:
- Hacer lo que debe hacerse solo cuando sea necesario
- Establezca el estado de cambio de la tarea en función de lo que realmente sucedió (muestra
ok
cuando el estado deseado ya existe ychanged
cuando tiene que hacer cambios)
Habiendo dicho eso, si Ud. real ¿Necesitas realizar una acción en el sistema operativo? Después de todo, a veces no tiene un módulo Ansible específico que pueda realizar tareas por usted.
Bueno, hay algunas opciones para hacer esto, dependiendo del sistema operativo que se ejecute en su objetivo.
Para Linux, puede utilizar uno de los siguientes módulos:
- Ordenar: El comando pasado como parámetro no Procesado por el shell, por lo que las variables de entorno y la redirección de E/S no funcionarán.
- caparazón: similar a un módulo
command
Pero usa el shell para ejecutar los comandos que se le pasan y acepta la redirección de E/S.
Para Windows puedes usar el módulo equivalente:
El comando que desea ejecutar en el destino puede ser un binario ejecutable o un script (script de shell en Linux, caja de poder en Windows).Si es un script, es posible que deba usar Copiar o win_copy El módulo envía el script a su máquina de destino, donde luego puede ejecutarlo.
Esencialmente, puede enviar y ejecutar scripts que contengan su lógica.
un estado mental
Ansible no es un lenguaje de programación, pero lo ayuda a tener un marco para un lenguaje de programación cuando lo usa. Después de esta publicación, es posible que (¿quizás debido a algunos mensajes subliminales?) comience a sentirse un poco como Ansible Jedi.