Está en la página 1de 440

Descargado en: eybooks.

com
ANSIBLE
Automatización para todos


ANSIBLE
Automatización para todos

Alberto González Rodríguez


Diseño de colección y pre-impresión:
Datos catalográficos
Grupo RC
Diseño cubierta: González, Alberto
Ansible. Automatización para todos
Cuadratín
Primera Edición
Alfaomega Grupo Editor, S.A. de C.V., México

ISBN: 978-607-538-330-9

Formato: 17 x 23 cm Páginas: 440

Ansible. Automatización para todos


Alberto González Rodríguez
ISBN: 978-84-947170-8-6 edición original publicada por RC Libros, Madrid, España.
Derechos reservados © 2018 RC Libros
Primera edición: Alfaomega Grupo Editor, México, septiembre 2018

© 2019 Alfaomega Grupo Editor, S.A. de C.V.


Dr. Isidoro Olvera (Eje 2 sur) No. 74, Col. Doctores, 06720, Ciudad de México.

Miembro de la Cámara Nacional de la Industria Editorial Mexicana


Registro No. 2317

Pág. Web: http://www.alfaomega.com.mx


E-mail: atencionalcliente@alfaomega.com.mx

ISBN: 978-607-538-330-9

Derechos reservados:
Esta obra es propiedad intelectual de su autor y los derechos de publicación en lengua española han
sido legalmente transferidos al editor. Prohibida su reproducción parcial o total por cualquier medio
sin permiso por escrito del propietario de los derechos del copyright.

Nota importante:
La información contenida en esta obra tiene un fin exclusivamente didáctico y, por lo tanto, no está
previsto su aprovechamiento a nivel profesional o industrial. Las indicaciones técnicas y programas
incluidos, han sido elaborados con gran cuidado por el autor y reproducidos bajo estrictas normas de
control. ALFAOMEGA GRUPO EDITOR, S.A. de C.V. no será jurídicamente responsable por:
errores u omisiones; daños y perjuicios que se pudieran atribuir al uso de la información comprendida
en este libro, ni por la utilización indebida que pudiera dársele. d e s c a r g a do en: e y b o o k s.c o m
Edición autorizada para venta en México y todo el continente americano.
Impreso en México. Printed in Mexico.

Empresas del grupo:


México: Alfaomega Grupo Editor, S.A. de C.V. – Dr. Isidoro Olvera (Eje 2 sur) No. 74, Col. Doctores,
C.P. 06720, Del. Cuauhtémoc, Ciudad de México – Tel.: (52-55) 5575-5022 – Fax: (52-55) 5575-2420 / 2490.
Sin costo: 01-800-020-4396 – E-mail: atencionalcliente@alfaomega.com.mx
Colombia: Alfaomega Colombiana S.A. – Calle 62 No. 20-46, Barrio San Luis, Bogotá, Colombia,
Tels.: (57-1) 746 0102 / 210 0415 – E-mail: cliente@alfaomega.com.co
Chile: Alfaomega Grupo Editor, S.A. – Av. Providencia 1443. Oficina 24, Santiago, Chile
Tel.: (56-2) 2235-4248 – Fax: (56-2) 2235-5786 – E-mail: agechile@alfaomega.cl
Argentina: Alfaomega Grupo Editor Argentino, S.A. – Av. Córdoba 1215, piso 10, CP: 1055, Buenos Aires, Argentina,
Tel./Fax: (54-11) 4811-0887 y 4811 7183 – E-mail: ventas@alfaomegaeditor.com.ar
Dedicado a todos los compañeros con los que he trabajado, en especial a los de la
Universidad de Vigo. De todos he aprendido y han hecho que progresara laboral y
personalmente.

A Miriam y a Jonathan, por estar siempre ahí ayudando cuando se les necesita.


ÍNDICE

CAPÍTULO 1. QUÉ ES ANSIBLE ............................................................................ 1


Introducción ......................................................................................................... 1
Glosario ................................................................................................................ 3
CAPÍTULO 2. INSTALACIÓN ................................................................................. 5
Introducción ......................................................................................................... 5
CentOS/RHEL/Scientific Linux 7............................................................................ 6
Ubuntu/Debian .................................................................................................... 6
Otras distribuciones/sistemas operativos. ........................................................... 7
Gentoo ......................................................................................................... 7
FreeBSD ........................................................................................................ 7
Solaris ........................................................................................................... 7
Arch Linux ..................................................................................................... 7
Código fuente ....................................................................................................... 7
PIP ........................................................................................................................ 8
CAPÍTULO 3. PRIMEROS PASOS .......................................................................... 9
Inventario ........................................................................................................... 12
Patrones ............................................................................................................. 15
YAML .................................................................................................................. 17
ANSIBLE

Inventario en formato YAML .............................................................................. 20


Inventario dinámico ........................................................................................... 21
Combinar inventarios ......................................................................................... 25
Ansible en modo Ad-Hoc .................................................................................... 26
Configuración ..................................................................................................... 32
Windows ............................................................................................................ 35
CAPÍTULO 4. PLAYBOOKS ................................................................................. 37
Introducción ....................................................................................................... 37
Patrones ............................................................................................................. 40
Opciones ansible-playbook ................................................................................ 41
Variables ............................................................................................................ 41
Handlers ............................................................................................................. 43
Include e import ................................................................................................. 45
Prioridad variables ............................................................................................. 49
Roles ................................................................................................................... 50
Plantillas ............................................................................................................. 54
Condiciones ........................................................................................................ 55
Bucles ................................................................................................................. 58
with_items ..................................................................................................... 58
with_nested ................................................................................................... 60
with_dict ........................................................................................................ 61
Register .............................................................................................................. 63
delegate_to ........................................................................................................ 64
ignore_errors ..................................................................................................... 65
failed_when y changed_when ........................................................................... 68
Bloques .............................................................................................................. 69
CAPÍTULO 5. MÓDULOS.................................................................................... 73
Introducción ....................................................................................................... 73

VIII © Alfaomega-RC Libros


ÍNDICE

Módulos tratados de fichero .............................................................................. 76


Argumentos SELINUX ..................................................................................... 77
Argumentos PERMISOS .................................................................................. 77
Módulo ACL .................................................................................................... 78
Módulo ARCHIVE............................................................................................ 80
Módulo ASSEMBLE ......................................................................................... 81
Módulo BLOCKINFILE ..................................................................................... 83
Módulo COPY ................................................................................................. 84
Módulo FETCH................................................................................................ 86
Módulo FILE ................................................................................................... 87
Módulo FIND .................................................................................................. 89
Módulo INI_FILE ............................................................................................. 92
Módulo LINEINFILE ......................................................................................... 93
Módulo REPLACE ............................................................................................ 96
Módulo STAT .................................................................................................. 97
Módulo TEMPLATE ......................................................................................... 99
Módulo UNARCHIVE..................................................................................... 100
MÓDULOS DE GESTOR DE PAQUETES .............................................................. 102
Módulo CPANM............................................................................................ 104
Módulo EASY_INSTALL ................................................................................. 105
Módulo PEAR ............................................................................................... 106
Módulo PIP ................................................................................................... 107
Módulo APT.................................................................................................. 109
Módulo APT_KEY.......................................................................................... 111
Módulo APT_REPOSITORY............................................................................ 112
Módulo DNF ................................................................................................. 113
Módulo PACKAGE......................................................................................... 114

© Alfaomega-RC Libros IX
ANSIBLE

Módulo PACMAN ......................................................................................... 115


Módulo YUM ................................................................................................ 116
Módulo YUM_REPOSITORY .......................................................................... 118
Módulo REDHAT_SUBSCRIPTION ................................................................. 120
Módulo ZYPPER ............................................................................................ 122
Módulo ZYPPER_REPOSITORY ...................................................................... 123
MÓDULOS PARA EJECUTAR COMANDOS ......................................................... 125
Módulo COMMAND ..................................................................................... 125
Módulo EXPECT ............................................................................................ 126
Módulo RAW ................................................................................................ 127
Módulo SCRIPT ............................................................................................. 127
Módulo SHELL .............................................................................................. 128
Módulo TELNET ............................................................................................ 130
MÓDULOS UTILIDADES .................................................................................... 131
Módulo META .............................................................................................. 131
Módulo ASSERT ............................................................................................ 133
Módulo FAIL ................................................................................................. 134
Módulo PAUSE ............................................................................................. 134
Módulo SET_FACT ........................................................................................ 135
Módulo SET_STATS ...................................................................................... 136
Módulo WAIT_FOR....................................................................................... 137
Módulo WAIT_FOR_CONNECTION ............................................................... 140
MÓDULOS NOTIFICACIONES ............................................................................ 141
Módulo HIPCHAT.......................................................................................... 143
Módulo IRC................................................................................................... 144
Módulo JABBER ............................................................................................ 145
Módulo MAIL................................................................................................ 147

X © Alfaomega-RC Libros
ÍNDICE

Módulo PUSHBULLET ................................................................................... 148


Módulo PUSHOVER ...................................................................................... 150
Módulo ROCKETCHAT .................................................................................. 150
Módulo SLACK .............................................................................................. 152
Módulo SYSLOGGER ..................................................................................... 153
Módulo TELEGRAM ...................................................................................... 154
MÓDULOS BASE DE DATOS .............................................................................. 156
Módulo MYSQL_DB ...................................................................................... 157
Módulo MYSQL_USER .................................................................................. 158
Argumentos POSTGRESQL............................................................................ 161
Módulo POSTGRESQL_DB ............................................................................ 161
Módulo POSTGRESQL_USER ........................................................................ 163
Módulo POSTGRESQL_PRIVS........................................................................ 164
Módulo POSTGRESQL_SCHEMA ................................................................... 166
Módulo MONGODB_USER ........................................................................... 167
MÓDULOS SISTEMA ......................................................................................... 169
Módulo ALTERNATIVES ................................................................................ 171
Módulo AUTHORIZED_KEYS ......................................................................... 173
Módulo CRON .............................................................................................. 174
Módulo FILESYSTEM ..................................................................................... 176
Módulo FIREWALLD ..................................................................................... 177
Módulo GETENT ........................................................................................... 179
Módulo GROUP ............................................................................................ 180
Módulo HOSTNAME ..................................................................................... 182
Módulo IPTABLES ......................................................................................... 182
Módulo KNOWN_HOSTS .............................................................................. 185
Módulo LVG ................................................................................................. 185

© Alfaomega-RC Libros XI
ANSIBLE

Módulo LVOL................................................................................................ 186


Módulo MODPROBE..................................................................................... 188
Módulo MOUNT ........................................................................................... 188
Módulo PARTED ........................................................................................... 190
Módulo SEBOOLEAN .................................................................................... 191
Módulo SEFCONTEXT ................................................................................... 192
Módulo SELINUX .......................................................................................... 193
Módulo SELINUX_PERMISSIVE ..................................................................... 194
Módulo SEPORT ........................................................................................... 195
Módulo SERVICE........................................................................................... 196
Módulo SETUP .............................................................................................. 197
Módulo SYSCTL............................................................................................. 199
Módulo SYSTEMD ......................................................................................... 200
Módulo TIMEZONE....................................................................................... 201
Módulo USER ............................................................................................... 202
MÓDULOS WINDOWS ...................................................................................... 204
Módulo WIN_PING ....................................................................................... 209
Módulo WIN_CHOCOLATEY ......................................................................... 209
Módulo WIN_COMMAND ............................................................................ 211
Módulo WIN_COPY ...................................................................................... 212
Módulo WIN_ENVIRONMENT ...................................................................... 213
Módulo WIN_FEATURE ................................................................................ 214
Módulo WIN_FILE ........................................................................................ 215
Módulo WIN_FIREWALL ............................................................................... 215
Módulo WIN_FIREWALL_RULE..................................................................... 216
Módulo WIN_GROUP ................................................................................... 218
Módulo WIN_LINEINFILE .............................................................................. 219

XII © Alfaomega-RC Libros


ÍNDICE

Módulo WIN_PACKAGE................................................................................ 220


Módulo WIN_SERVICE.................................................................................. 221
Módulo WIN_TEMPLATE .............................................................................. 223
Módulo WIN_USER ...................................................................................... 224
MÓDULOS CONTROL DE VERSIONES ................................................................ 226
Módulo BZR .................................................................................................. 227
Módulo GIT .................................................................................................. 227
Módulo GIT_CONFIG .................................................................................... 228
Módulo GITHUB_DEPLOY_KEY ..................................................................... 228
Módulo GITHUB_KEY ................................................................................... 229
Módulo GITHUB_HOOKS .............................................................................. 230
Módulo GITHUB_RELEASE............................................................................ 231
Módulo GITLAB_GROUP............................................................................... 232
Módulo GITLAB_PROJECT ............................................................................ 233
Módulo GITLAB_USER .................................................................................. 234
Módulo HG ................................................................................................... 235
Módulo SUBVERSION ................................................................................... 236
MÓDULOS INFRAESTRUCTURA WEB ................................................................ 237
Módulo APACHE2_MODULE ........................................................................ 238
Módulo HTPASSWD...................................................................................... 238
Módulo JBOSS .............................................................................................. 239
Módulo JENKINS_JOB ................................................................................... 240
Módulo JENKINS_PLUGIN ............................................................................ 241
Módulo JIRA ................................................................................................. 241
Módulo LETSENCRYPT .................................................................................. 242
Módulo SUPERVISORCTL .............................................................................. 244
MÓDULOS CLOUD ............................................................................................ 244

© Alfaomega-RC Libros XIII


ANSIBLE

AMAZON ...................................................................................................... 245


Módulo EC2 .............................................................................................. 245
Módulo EC2_KEY ...................................................................................... 247
Módulo EC2_GROUP ................................................................................ 247
Módulo EC2_SUBNET ............................................................................... 249
Módulo EC2_VOL ..................................................................................... 250
Módulo IAM ............................................................................................. 251
AZURE........................................................................................................... 252
Módulo AZURE_RM_RESOURCEGROUP ................................................... 253
Módulo AZURE_RM_MANAGED_DISK ..................................................... 254
Módulo AZURE_RM_NETWORK ............................................................... 255
Módulo AZURE_RM_SECURITYGROUP..................................................... 256
Módulo AZURE_RM_VIRTUALMACHINE .................................................. 257
DIGITALOCEAN ............................................................................................. 259
Módulo DIGITAL_OCEAN .......................................................................... 259
Módulo DIGITAL_OCEAN_BLOCK_STORAGE ............................................ 260
Módulo DIGITAL_OCEAN_FLOATING_IP .................................................. 261
Módulo DIGITAL_OCEAN_SSHKEY ............................................................ 262
Módulo DIGITAL_OCEAN_TAG ................................................................. 263
DOCKER ........................................................................................................ 263
Módulo DOCKER_CONTAINER.................................................................. 264
Módulo DOCKER_IMAGE.......................................................................... 265
Módulo DOCKER_LOGIN .......................................................................... 266
Módulo DOCKER_NETWORK .................................................................... 267
Módulo DOCKER_VOLUME ...................................................................... 267
GOOGLE........................................................................................................ 268
Módulo GCE ............................................................................................. 268

XIV © Alfaomega-RC Libros


ÍNDICE

Módulo GCE_LABELS ................................................................................ 269


Módulo GCE_NET ..................................................................................... 270
Módulo GCE_PD ....................................................................................... 272
Módulo GCE_TAG ..................................................................................... 273
LIBVIRT ......................................................................................................... 274
Módulo VIRT............................................................................................. 274
Módulo VIRT_NET .................................................................................... 275
Módulo VIRT_POOL.................................................................................. 276
OPENSTACK .................................................................................................. 277
Módulo OS_PROJECT................................................................................ 277
Módulo OS_NETWORK ............................................................................. 278
Módulo OS_SUBNET................................................................................. 279
Módulo OS_ROUTER ................................................................................ 280
Módulo OS_SECURITY_GROUP ................................................................ 281
Módulo OS_SECURITY_GROUP_RULE ...................................................... 282
Módulo OS_SERVER ................................................................................. 284
MÓDULOS CLUSTERING ................................................................................... 285
MÓDULOS MONITORING ................................................................................. 286
ZABBIX .............................................................................................................. 287
Módulo ZABBIX_GROUP............................................................................... 287
Módulo ZABBIX_HOST.................................................................................. 288
Módulo ZABBIX_HOSTMACRO ..................................................................... 289
Módulo ZABBIX_MAINTENANCE .................................................................. 290
Módulo ZABBIX_SCREEN .............................................................................. 291
MÓDULOS IDENTIDAD ..................................................................................... 292
CYBERARK......................................................................................................... 292
IPA .................................................................................................................... 292

© Alfaomega-RC Libros XV
ANSIBLE

Módulo IPA_DNSRECORD ............................................................................ 293


Módulo IPA_GROUP ..................................................................................... 293
Módulo IPA_HOST ........................................................................................ 294
Módulo IPA_ROLE ........................................................................................ 295
Módulo IPA_USER ........................................................................................ 295
Módulo OPENDJ ............................................................................................... 297
MÓDULOS INVENTARIO ................................................................................... 297
Módulo ADD_HOST ...................................................................................... 297
Módulo GROUP_BY ...................................................................................... 299
MÓDULOS MENSAJERÍA ................................................................................... 301
MÓDULOS CRIPTOGRAFÍA................................................................................ 301
Ejemplo ........................................................................................................ 302
MÓDULOS HERRAMIENTAS DE RED ................................................................. 303
Módulo GET_URL ......................................................................................... 304
Módulo HAPROXY ........................................................................................ 305
Módulo LDAP_ENTRY ................................................................................... 305
Módulo NSUPDATE ...................................................................................... 307
Módulo SLURP .............................................................................................. 307
Módulo URI .................................................................................................. 308
MÓDULOS ALMACENAMIENTO........................................................................ 309
MÓDULOS ADMINISTRACIÓN REMOTA ........................................................... 311
MÓDULOS REDES ............................................................................................. 312

CAPÍTULO 6. CARACTERÍSTICAS AVANZADAS ................................................. 315


ETIQUETAS (TAGS) ........................................................................................... 315
LOOKUPS .......................................................................................................... 318
CSVFILE ......................................................................................................... 320
DIG ............................................................................................................... 321

XVI © Alfaomega-RC Libros


ÍNDICE

ENV............................................................................................................... 321
FILE ............................................................................................................... 322
INI ................................................................................................................. 322
PASSWORD ................................................................................................... 323
PIPE .............................................................................................................. 323
URL ............................................................................................................... 324
FILTROS ............................................................................................................ 325
VAULT............................................................................................................... 348
ANSIBLE-VAULT ............................................................................................ 348
create ....................................................................................................... 348
edit ........................................................................................................... 349
encrypt ..................................................................................................... 349
decrypt ..................................................................................................... 350
rekey ........................................................................................................ 350
view .......................................................................................................... 350
ANSIBLE-PLAYBOOK ..................................................................................... 351
TAREAS ASÍNCRONAS ....................................................................................... 352
OPCIONES AVANZADAS .................................................................................... 355
EXTENDER ANSIBLE .......................................................................................... 357
LOOKUP ........................................................................................................ 357
FILTROS ........................................................................................................ 358
MÓDULOS .................................................................................................... 359
INVENTARIO ................................................................................................. 361
Bucles avanzados ............................................................................................. 361
Local facts......................................................................................................... 364
CAPÍTULO 7. ANSIBLE GALAXY ........................................................................ 367
INTRODUCCIÓN................................................................................................ 367

© Alfaomega-RC Libros XVII


ANSIBLE

COMANDO ANSIBLE-GALAXY ........................................................................... 369


IMPORTAR NUESTRO ROL PARA GALAXY ......................................................... 371
FICHERO REQUISITOS ....................................................................................... 377
CAPÍTULO 8. ANSIBLE TOWER ........................................................................ 379
INTRODUCCIÓN................................................................................................ 379
INSTALACIÓN ................................................................................................... 380
CONFIGURACIÓN ............................................................................................. 383
Organización ................................................................................................ 384
Usuarios ....................................................................................................... 384
Equipos ......................................................................................................... 386
Credenciales ................................................................................................. 387
Trabajos de gestión ...................................................................................... 388
Scripts de inventario .................................................................................... 388
Notificaciones............................................................................................... 389
Licencia......................................................................................................... 390
Grupo de instancias...................................................................................... 390
Configurar tower .......................................................................................... 391
Autentificación ......................................................................................... 391
Trabajos .................................................................................................... 392
Sistema ..................................................................................................... 392
Proyectos ......................................................................................................... 394
Inventarios ....................................................................................................... 395
Fuentes......................................................................................................... 397
AD HOC......................................................................................................... 398
Credenciales ..................................................................................................... 399
Plantillas ........................................................................................................... 400
Plantillas de flujo de trabajo ............................................................................ 401

XVIII © Alfaomega-RC Libros


ÍNDICE

Trabajos............................................................................................................ 403
Programar ........................................................................................................ 405
Notificaciones .................................................................................................. 406
Permisos ........................................................................................................... 407
Proyectos ..................................................................................................... 407
Inventarios ................................................................................................... 407
Plantillas ....................................................................................................... 408
Credenciales ................................................................................................. 409
Avanzado.......................................................................................................... 410
Inventario inteligente ................................................................................... 410
Encuesta (survey) ......................................................................................... 411
Callback ........................................................................................................ 413
Copia de seguridad / Restauración .............................................................. 414

ÍNDICE ANALÍTICO .....……………………………………………………………………………………417

© Alfaomega-RC Libros XIX


QUÉ ES ANSIBLE

INTRODUCCIÓN

Ansible se ha convertido en la herramienta de automatización más popular en


la actualidad. Es gratuita, de código abierto y permite automatizar todos los
elementos de una infraestructura: desde servidores hasta dispositivos de red. Los
sistemas operativos que se pueden gestionar son Linux y los derivados de UNIX
(AIX, Solaris y BSD), en la parte de red, y soporta los dispositivos más populares
(Cisco, Arista, F5, Palo Alto, etc.)

En los últimos años ha habido una evolución desde una infraestructura on site
a una infraestructura en la nube (cloud). Ansible permite trabajar con los
proveedores más famosos de Cloud para automatizar no solo el despliegue de
instancias, sino también para gestionar los diferentes componentes en la nube,
como pueden ser redes, grupos de seguridad, claves públicas y direcciones IP
públicas. Entre la amplia lista de proveedores en la nube que se pueden gestionar,
se encuentran Amazon Web Services, Azure y Google Cloud Platform.

Ansible sirve para instalar aplicaciones, orquestar servicios y tareas más


avanzadas como entrega continua (continuous deployment, CD) e integración
continua (continuous integration, CI). También es una solución ideal para la
estandarización de sistema operativo (misma configuración, mismas versiones) y
la administración de servicios centralizados (Directorio Activo, DNS, entre otros).
ANSIBLE

Para los clientes que posean su propia infraestructura como servicio (IaaS,
Infrastructure as a Service) también posee soporte para una gran variedad, entre
los que destacan VMware, OpenStack y Ovirt (Red Hat Virtualization).

Ansible posee la comunidad de colaboradores más amplias (cerca de 3000


personas) dentro de los softwares de automatización de código abierto y
aproximadamente cada dos meses se publica una nueva versión con nuevas
características y correcciones de errores (bugs).

La gran popularidad obtenida por Ansible en comparación con sus


competidores (Puppet, Chef o SaltStack) se debe principalmente a:

● Soporte para la mayoría de distribuciones.


● Instalación simple y de tamaño reducido.
● Rápida curva de aprendizaje: la sintaxis es simple y no se necesitan
conocimientos de programación.
● No es necesario tener un agente en los servidores (o dispositivos) que se
administran, que conlleva las siguientes ventajas:
○ Mayor seguridad al no necesitar mantener los agentes y posibles
bugs (errores) de los mismos.
○ La conexión se realiza a través de SSH o WinRM (para nodos
Windows), no se necesita puertos extra y solo se requiere
autentificación estándar: con usuario y contraseña o con clave pública.
● Gran cantidad y diversidad de elementos que se pueden gestionar.

Algunas de las desventajas que se han indicado de Ansible, comparado con


otros competidores se listan a continuación:
● No es tan potente como otros productos para la administración de
configuraciones.
● En entornos con grandes cantidades de elementos a administrar, se
requieren configuraciones avanzadas para obtener un rendimiento óptimo.
● A pesar de la regular publicación de nuevas versiones que incluye solución
de problemas, hay muchos módulos (encargados de gestionar elementos)
donde la corrección suele ser tardía.

Las compañías en la actualidad requieren acelerar los procesos, desde el


suministro de sistemas hasta el despliegue de aplicaciones en producción. Por ello
la automatización se convierte en un elemento esencial en el crecimiento de las
empresas y en el rendimiento de sus tareas. Ansible se ha convertido en el aliado
perfecto para desarrolladores, administradores de sistemas y DevOps.

2 © Alfaomega-RC Libros
CAPÍTULO 1: QUÉ ES ANSIBLE

Glosario
Los diferentes elementos que resumimos a continuación se detallarán en
profundidad a lo largo del libro.

Playbook Lista de jugadas (Plays) a realizar en nodos


especificados.
Play Lista de tareas (Tasks) a realizar en los nodos
especificados por el Playbook.
Inventario Listado, estático o dinámico, con lista de
nodos a administrar y la información necesaria
de cada uno de ellos.
Nodo Elemento a administrar: servidor, router u otro
elemento administrable.
Tarea La definición de una acción a realizar.
Acción La acción a realizar en un nodo.
Módulo Unidades de trabajo que se copian al nodo
administrado y ejecuta la tarea requerida.
Ansible contiene más de 1500 módulos.
Argumento Los valores necesarios para que el módulo
realice la acción.
Plantilla Fichero dinámico utilizado principalmente para
configuraciones o ficheros con valores
volátiles.
Facts Información útil obtenida del nodo a ser
utilizada en plantilla o en módulos.
Variable Valores especificados estática o dinámicamente
a ser utilizados por módulos y plantillas.
Rol Agrupación de tareas, ficheros y plantillas que
pueden ser reutilizados en diferentes
proyectos. Además existe un repositorio público
con gran variedad.
Condición Comprobación realizada para saber si una tarea
debe ser ejecutada.
Idempotencia Propiedad de que una tarea ejecutada varias
veces mantiene el mismo estado deseado.

© Alfaomega-RC Libros 3
INSTALACIÓN

INTRODUCCIÓN

Como se ha indicado en la introducción, la administración de los nodos se


realiza a través del protocolo SSH o a través de WinRM. No es necesario instalar
un agente en ellos, solo es necesario instalar Ansible en un nodo donde se iniciará
la comunicación y se realizarán las tareas especificadas.

Este nodo se denomina máquina de control (Control Machine). En este nodo


no se instalará software adicional, como podría ser base de datos o servicios que
tengan que ser iniciados o mantenidos.

La instalación recomendada para las distribuciones CentOS, Fedora, Red Hat


Enterprise Linux (™), Debian o Ubuntu, es utilizar el gestor de paquetes propio de
cada una de ellas. Para otras distribuciones o en el caso de desear tener siempre
la última versión, la forma recomendada es utilizar el gestor de paquetes de
Python llamado pip.

Los requisitos para la máquina de control son los siguientes: Python 2


(Versiones 2.6 o 2.7) o Python 3 (Versiones 3.5 o posteriores). Windows no se
soporta como máquina de control.

Los nodos a automatizar se denominan nodo gestionado (Managed Node). En


caso de sistemas operativos, en estos nodos solo es necesario tener Python 2.5 o
posterior, por defecto se utiliza sftp para copiar los ficheros necesarios a ese
nodo, pero es posible configurar el uso de scp.
ANSIBLE

CentOS/RHEL/Scientific Linux 7
En las últimas versiones de Ansible ha habido un cambio del repositorio donde
están disponible los paquetes. Anteriormente (y actualmente para las versiones 6)
se ofrecía a través de EPEL (Extra Packages for Enterprise Linux) pero en las
últimas versiones, a partir de la 2.3, se ofrece a través del repositorio Extras.

Para CentOS utilizaremos el siguiente comando para habilitar el repositorio.

yum-config-manager --enablerepo=extras

Para Red Hat Enterprise Linux utilizaremos el siguiente comando.

subscription-manager repos --enable=rhel-7-server-extras-rpms

La instalación en ambas distribuciones es simple:

# yum install ansible


[..]
Installed:
ansible.noarch 0:2.4.2.0-2.el7
Dependency Installed:
python-cffi.x86_64 0:1.6.0-5.el7 python-enum34.noarch
0:1.0.4-1.el7 python-idna.noarch 0:2.4-1.el7 python-
ipaddress.noarch 0:1.0.16-2.el7 python-passlib.noarch
0:1.6.5-2.el7 python-ply.noarch 0:3.4-11.el7
python-pycparser.noarch 0:2.14-1.el7 python2-
cryptography.x86_64 0:1.7.2-1.el7_4.1 python2-
jmespath.noarch 0:0.9.0-3.el7
Dependency Updated:
openssl.x86_64 1:1.0.2k-8.el7 openssl-libs.x86_64
1:1.0.2k-8.el7
Complete!

Ubuntu/Debian
Para Ubuntu debemos instalar el paquete software-properties-common y
añadir el repositorio PPA de ansible.
$ sudo apt-get install software-properties-common
$ sudo apt-add-repository ppa:ansible/ansible

6 © Alfaomega-RC Libros
CAPÍTULO 2: INSTALACIÓN

$ sudo apt-get update


$ sudo apt-get install ansible

Para Debian debemos configurar el repositorio dentro de nuestros sources.list


echo "deb http://ppa.launchpad.net/ansible/ansible/ubuntu
trusty main" >> /etc/apt/sources.list

A continuación confiamos en la clave GPG de dicho repositorio e instalamos el


paquete ansible.
$ sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-
keys 93C4A3FD7BB9C367
$ sudo apt-get update
$ sudo apt-get install ansible

Otras distribuciones/sistemas operativos

Gentoo

$ sudo emerge -av app-admin/ansible

FreeBSD

$ sudo pkg install ansible

Solaris

# pkgadd -d http://get.opencsw.org/now
# /opt/csw/bin/pkgutil -i ansible

Arch Linux

$ sudo pacman -S ansible

Código fuente
Desde código fuente (Ejemplo usando el tarball de la versión 2.4.0):

© Alfaomega-RC Libros 7
ANSIBLE

# wget https://github.com/ansible/ansible/archive/v2.4.0.0-
1.tar.gz
# tar xvfz v2.4.0.0-1.tar.gz
# cd ansible-2.4.0.0-1/
# python setup.py install

PIP
Para instalar PIP se puede utilizar easy_install y utilizando pip podemos instalar
la última versión de Ansible o una versión específica (ejemplo: ansible==2.4.2.0)

# easy_install pip
Searching for pip
Best match: pip 1.5.4
Adding pip 1.5.4 to easy-install.pth file
Installing pip script to /usr/local/bin
Installing pip2.7 script to /usr/local/bin
Installing pip2 script to /usr/local/bin
Using /usr/lib/python2.7/dist-packages
Processing dependencies for pip
Finished processing dependencies for pip# pip install
ansible
Downloading/unpacking ansible
Downloading ansible-2.4.3.0.tar.gz (6.5MB): 6.5MB
downloaded
Running setup.py
(path:/tmp/pip_build_root/ansible/setup.py) egg_info for
package ansible
[...]Successfully installed ansible paramiko pyasn1 bcrypt
pynacl
Cleaning up...

Para comprobar la versión instalada utilizaremos la opción --version:

# ansible --version
ansible 2.4.3.0
config file = /etc/ansible/ansible.cfg
configured module search path = [u'/usr/share/ansible']
ansible python module location =
/usr/local/lib/python2.7/dist-packages/ansible
executable location = /usr/local/bin/ansible
python version = 2.7.6 (default, Nov 23 2017, 15:49:48)
[GCC 4.8.4]

8 © Alfaomega-RC Libros
PRIMEROS PASOS

INTRODUCCIÓN

Una vez instalado Ansible, en este capítulo se detallan los primeros pasos que
podemos realizar para comprender el funcionamiento y cómo nos conectaremos
a los nodos que vamos a administrar.

El primer paso es definir los servidores que queremos administrar, para ello los
añadiremos dentro del fichero /etc/ansible/hosts, en el caso de que este fichero
no incluya ningún nodo, solo localhost (el servidor donde estamos ejecutando
Ansible) estará disponible.

Los nodos definidos dentro del fichero hosts, por defecto, serán configurados
para que la conexión a ellos se realice a través de SSH. Un ejemplo de este fichero
para administrar tres nodos es el siguiente (las líneas que empiezan por "#" son
comentarios).

## db-[99:101]-node.example.com
www.oforte.net
cloud.oforte.net
lab.oforte.net

Para listar los servidores definidos, utilizaremos el siguiente comando:

# ansible --list-hosts all


hosts (3):
ANSIBLE

www.oforte.net
cloud.oforte.net
lab.oforte.net

Podemos comprobar la conexión a los servidores definidos a través del


siguiente comando (donde all indica todos los servidores) que explicaremos con
más detalle en el siguiente capítulo.

# ansible all -m pingcloud.oforte.net | SUCCESS => {


"changed": false,
"ping": "pong"
}
www.oforte.net | SUCCESS => {
"changed": false,
"ping": "pong"
}
lab.oforte.net | UNREACHABLE! => {
"changed": false,
"msg": "Failed to connect to the host via ssh: Permission
denied (publickey,password).\r\n",
"unreachable": true
}

En este caso vemos que la conexión a dos servidores ha sido correcta, pero en
cambio el último servidor nos dice que no se ha podido conectar por SSH. Esto es
debido a que la clave pública del usuario que está ejecutando el comando ansible,
no ha sido incluida dentro de las claves autorizadas de dicho servidor. Podemos
copiar la clave pública usando ssh-copy-id y comprobar de nuevo la conexión:

# ssh-copy-id root@lab.oforte.net
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new
key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if
you are prompted now it is to install the new keys
root@lab.oforte.net's password:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh root@lab.oforte.net'"
and check to make sure that only the key(s) you wanted were added.
# ansible lab.oforte.net -m ping
lab.oforte.net | SUCCESS => {
"changed": false,
"ping": "pong"
}

10 © Alfaomega-RC Libros
CAPÍTULO 3: PRIMEROS PASOS

También es posible autenticarse al servidor con un usuario distinto (con la


opción --user [-u]) al que estamos ejecutando los comandos (si estamos como
usuario root, intentará conectarse con el mismo usuario) y podemos utilizar
contraseña (con la opción --ask-pass [-k]) en vez de clave pública.

Para utilizar la contraseña es necesario primero instalar la aplicación sshpass.

# apt-get install -y sshpass


[..]Preparing to unpack .../sshpass_1.05-1_amd64.deb ...
Unpacking sshpass (1.05-1) ...
Processing triggers for man-db (2.7.0.2-5) ...
Setting up sshpass (1.05-1) ...

Ejemplo conectando con el usuario agonzalez en vez del usuario root y


solicitando la contraseña del usuario:

# ansible lab.oforte.net -u agonzalez -k -m ping


SSH password:
lab.oforte.net | SUCCESS => {
"changed": false,
"ping": "pong"
}

La conexión a localhost no se realizará usando SSH (cuando no está dentro del


fichero hosts), sino que las acciones se realizarán directamente internamente. En
caso de añadir localhost al fichero /etc/ansible/hosts debemos especificarle el
parámetro ansible_connection=local, en caso contrario intentará conectarse por
SSH.

www.oforte.net
cloud.oforte.net
lab.oforte.net
localhost ansible_connection=local

Una vez que hemos comprobado la conexión, es posible ejecutar comandos de


una manera simple para comprobar el funcionamiento de Ansible. En el siguiente
ejemplo, mostraremos el resultado del comando uptime en cada uno de los
servidores.

# ansible all -a "uptime"


localhost | SUCCESS | rc=0 >>

© Alfaomega-RC Libros 11
ANSIBLE

20:30:23 up 1:07, 1 user, load average: 0.00, 0.01, 0.05


cloud.oforte.net | SUCCESS | rc=0 >>
21:34:05 up 27 days, 3:38, 2 users, load average: 0.70, 0.78, 0.73
www.oforte.net | SUCCESS | rc=0 >>
21:30:23 up 424 days, 9:54, 1 user, load average: 0.00, 0.01, 0.05
lab.oforte.net | SUCCESS | rc=0 >>
20:30:23 up 326 days, 10:46, 63 users, load average: 0.00, 0.00, 0.00

En el caso de que tengamos sudo configurado en el sistema, podemos utilizar


la opción --become (-b) para cambiar del usuario con el que nos conectamos al
usuario root.

# ansible lab.oforte.net -u agonzalez --ask-pass –a "id"


SSH password:
lab.oforte.net | SUCCESS | rc=0 >>
uid=1000(agonzalez) gid=1000(agonzalez)
groups=1000(agonzalez)
# ansible lab.oforte.net -u agonzalez --ask-pass -a "id" -b
SSH password:
lab.oforte.net | SUCCESS | rc=0 >>
uid=0(root) gid=0(root) groups=0(root)

Inventario
Ansible puede administrar distintas infraestructuras en diferentes entornos,
para ello debemos tener un inventario con los nodos a administrar. Como se
indica anteriormente por defecto se define en /etc/ansible/hosts pero con la
opción --inventory [-i] podemos especificar otro fichero que contenga una lista de
nodos a utilizar. Más adelante veremos los inventarios dinámicos, para obtener
una lista de los nodos automáticamente de un proveedor o de un CMDB (base de
datos de gestión de configuración).

El formato del fichero estático puede ser en INI o YAML (detallaremos este
formato posteriormente). Dentro del inventario podemos agrupar los nodos en
grupos y los grupos en grupos superiores. Un nodo puede pertenecer a varios
grupos, veamos un ejemplo:

[webs]
www.oforte.net
portal.oforte.net
[cloud]

12 © Alfaomega-RC Libros
CAPÍTULO 3: PRIMEROS PASOS

cloud.oforte.net
lab.oforte.net
[admin]
cloud.oforte.net
localhost ansible_connection=local

En este ejemplo se definen tres grupos (webs, cloud, admin) y el nodo


cloud.oforte.net pertenece a dos de ellos (cloud, admin). La definición de un
grupo se hace entre corchetes y la lista de nodos a continuación pertenecerá al
mismo. Los grupos son útiles para agrupar servidores con cierta afinidad:

● Geográficamente, por ejemplo: Madrid, México, Datatacenter1, etc.


● Aplicación que sirven, por ejemplo: webs, bbdds, backup, etc.
● Tipo de sistema operativo, por ejemplo: Linux, Aix, Windows, etc.
● Entorno del nodo: producción, desarrollo, pruebas, etc.

A un nodo se le pueden especificar parámetros de conexión o diferentes


valores para utilizar durante tareas de automatización (en este ejemplo definimos
una variable llamada entorno):

portal.oforte.net ansible_user=agonzalez ansible_port=2222


ansible_host=10.0.2.2 entorno=DEV

Dichas variables pueden ser:

● ansible_user: Define el usuario con el que conectarse al nodo.


● ansible_host: Define la IP con la que conectarse a dicho nodo.
● ansible_port: Define el puerto a utilizar para la conexión.
● ansible_ssh_pass: Define la contraseña para la conexión (no
recomendado debido por motivos de seguridad).
● ansible_become: Define si debe utilizar sudo (u otro método de escalada
de permisos) para ejecutar las tareas.
● ansible_connection: Tipo de conexión: ssh, local o docker.
● ansible_become_method: Método a utilizar para escalar permisos:
sudo/su/pbrun/pfexec/doas/dzdo/ksu.
● ansible_become_user: Usuario a utilizar para la escalada de permisos.

Es posible definir dichos parámetros o valores a nivel de grupo en vez de


individualmente por nodo, para ello haremos lo siguiente:

© Alfaomega-RC Libros 13
ANSIBLE

[webs]
www.oforte.net
portal.oforte.net
[webs:vars]
ansible_port=2222
entorno=PROD

En este caso utilizamos la sintaxis [grupo:vars] para definir los parámetros y las
variables (personalizadas) para todos los nodos dentro de ese grupo. Para la
creación de un grupo que contenta otros grupos, utilizaremos la sintaxis
[grupo:children] como se muestra a continuación:

[oforte:children]
webs
cloud

La lista de nodos para el nuevo grupo llamado oforte contendrá los servidores
de los grupos webs y cloud.

# ansible oforte --list-hosts


hosts (4):
www.oforte.net
portal.oforte.net
cloud.oforte.net
lab.oforte.net

Es posible definir los parámetros de conexión y las variables de los servidores,


asó como los grupos en ficheros separados. A continuación se muestra la
estructura:

|-/etc/ansible/hosts
|--/etc/ansible/host_vars/
|---/etc/ansible/host_vars/all.yml
|---/etc/ansible/host_vars/servidor1.yml
|---/etc/ansible/host_vars/servidor2.yml
|--/etc/ansible/group_vars/
|---/etc/ansible/group_vars/all.yml
|---/etc/ansible/group_vars/grupo1.yml
|---/etc/ansible/group_vars/grupo2.yml

En el caso de que el fichero sea hosts (que puede tener un nombre diferente),
la estructura es similar:

14 © Alfaomega-RC Libros
CAPÍTULO 3: PRIMEROS PASOS

|-/inventario/production/servidores
|--/inventario/production/host_vars/
|---/inventario/production/host_vars/all.yml
|---/inventario/production/host_vars/servidor1.yml
|---/inventario/production/host_vars/servidor2.yml
|-/inventario/production/group_vars/
|---/inventario/production/group_vars/all.yml
|---/inventario/production/group_vars/grupo1.yml
|---/inventario/production/group_vars/grupo2.yml

En estos ficheros las variables se definirían en formato YAML (que veremos


más adelante), aquí se muestra un ejemplo:

/inventario/production/host_vars/all.yml
entorno: prod
/inventario/production/host_vars/servidor1.yml
ansible_host: 192.168.100.10
ansible_port: 22
ansible_user: agonzalez

Patrones
En el inventario es posible utilizar patrones para definir la lista de nodos a
administrar. Si el nombre de los servidores contiene un esquema de nombre
común, es posible incluir esta sintaxis:

web[01:05].oforte.net http_port=80

Esto definirá una lista de 5 servidores con la variable http_port:

● web01.oforte.net
● web02.oforte.net
● web03.oforte.net
● web04.oforte.net
● web05.oforte.net

No solo la forma de rango número está permitido, sino también un rango


alfabético:

backup-[a:e].oforte.net backup_server=backup.oforte.net

© Alfaomega-RC Libros 15
ANSIBLE

Esto definirá una lista de 5 servidores con la variable http_port:

● backup-a.oforte.net
● backup-b.oforte.net
● backup-c.oforte.net
● backup-d.oforte.net
● backup-e.oforte.net

Un ejemplo completo de un inventario se muestra a continuación:

lab.oforte.net
[webs]
web[01:05].oforte.net http_port=80
[backup]
backup-[a:e].oforte.net backup_server=backup.oforte.net
[oforte:children]
webs
backup
[oforte:vars]
cliente=ofortenet

Como hemos visto anteriormente, se crea un grupo automáticamente llamado


all, que incluye toda la lista de servidores. Además, otro grupo llamado ungrouped
se crea para los nodos que no pertenecen a ningún grupo.

Listar todos.
# ansible all --inventory /inventarios/produccion --list-
hosts
hosts (11):
lab.oforte.net
web01.oforte.net
web02.oforte.net
web03.oforte.net
web04.oforte.net
web05.oforte.net
backup-a.oforte.net
backup-b.oforte.net
backup-c.oforte.net
backup-d.oforte.net
backup-e.oforte.net

16 © Alfaomega-RC Libros
CAPÍTULO 3: PRIMEROS PASOS

Listar los nodos que no pertenecen a un grupo.


# ansible ungrouped -i /inventarios/produccion --list-hosts
hosts (1):
lab.oforte.net
Listar hosts del grupo webs.
# ansible webs –I /inventarios/produccion --list-hosts
hosts (5):
web01.oforte.net
web02.oforte.net
web03.oforte.net
web04.oforte.net
web05.oforte.net
Listar todos los nodos de un grupo (oforte) padre que
incluirá grupos hijos.
# ansible oforte –i /inventarios/produccion --list-hosts
hosts (10):
web01.oforte.net
web02.oforte.net
web03.oforte.net
web04.oforte.net
web05.oforte.net
backup-a.oforte.net
backup-b.oforte.net
backup-c.oforte.net
backup-d.oforte.net
backup-e.oforte.net

YAML

YAML (YAML Ain't Markup Language) es un lenguaje de serialización de datos


de forma legible. Este formato para definir datos es muy simple (comparado con
XML o JSON) pero a la vez muy potente para definir diferentes estructuras de
datos.

En los inventarios hemos visto que el formato por defecto es INI, pero en las
últimas versiones los inventarios se pueden definir en formato YAML. Todas las
tareas a ejecutar en los servidores se definirán en este formato. Primero
observemos la sintaxis de este formato.

© Alfaomega-RC Libros 17
ANSIBLE

---
título: lista de empleados
numero: 3
puestos:
- CEO
- CTO
- CFO
...

En este ejemplo observamos que la primera línea contiene tres guiones (---) y
la última tres puntos (...) para definir el inicio y el final del fichero. Estas dos líneas
son opcionales y habitualmente se incluye solo la primera línea. En este ejemplo
hemos definido una variable llamada título de tipo cadena de texto y otra llamada
número de tipo numérico. La variable puestos es una lista de elementos, cada
elemento está indentado (con espacios es lo recomendado) e inicia con un guion
continuado por un espacio. Otra manera de definir una lista (aunque menos
legible) es la siguiente:

puestos: ['CEO', 'CTO', 'CFO']

YAML también nos permite crear una variable con una estructura de
diccionario (relacionando clave con un valor), ejemplo:

---
escritor:
nombre: Alberto
apellido: González
libros:
- Docker, guía práctica
- Ansible, automatización para todos
...

Un diccionario también es posible definirlo en una línea (se muestra otra vez lo
poco legible que puede ser):

escritor: {nombre: Alberto, apellido: González, libros: ["Docker,


guía práctica", "Ansible, automatización para todos"]}

Es posible también crear una lista de diccionarios, haciendo una estructura


compleja:

18 © Alfaomega-RC Libros
CAPÍTULO 3: PRIMEROS PASOS

---
escritores:
- alberto:
nombre: Alberto
apellido: González
libros:
- Docker, guía práctica
- Ansible, automatización para todos
- jonathan:
nombre: Jonathan
apellido: Veites
libros:
- Photoshop avanzado
...

Podemos definir un valor de verdadero o falso de estas maneras (en este


ejemplo se muestra que el carácter para los comentarios es la almohadilla [#]):

---
verdad1: True # Sirve también: true, TRUE
verdad2: yes # Sirve también: Yes
falso1: False # Sirve también: false, FALSE
falso1: no # Sirve también No
...

En el caso de querer utilizar una cadena de texto en vez de un valor de


verdadero o falso (también para valores numéricos, como enteros y decimales) se
utilizarán comillas dobles para ello.

---
cadena: "True"
cadena numero: "1.4"
...

YAML permite definir valores con múltiples líneas (usando el carácter especial
|) y la posibilidad de unirlas si fuese necesario (usando el carácter especial >).
Ejemplo:

---
separada_las_lineas: |
En un lugar de la Mancha,
de cuyo nombre no quiero acordarme,

© Alfaomega-RC Libros 19
ANSIBLE

no ha mucho tiempo que vivía un hidalgo


de los de lanza en astillero, adarga antigua,
rocín flaco y galgo corredor.
unidas_las_lineas: >
En un lugar de la Mancha,
de cuyo nombre no quiero acordarme,
no ha mucho tiempo que vivía un hidalgo
de los de lanza en astillero, adarga antigua,
rocín flaco y galgo corredor.
...

En la siguiente tabla se muestra el valor de las variables:

separada_las_lineas En un lugar de la Mancha, \nde cuyo


nombre no quiero acordarme, \nno ha
mucho tiempo que vivía un hidalgo \nde
los de lanza en astillero, adarga
antigua, \nrocín flaco y galgo corredor.
\n
unidas_las_lineas En un lugar de la Mancha, de cuyo nombre
no quiero acordarme, no ha mucho tiempo
que vivía un hidalgo de los de lanza en
astillero, adarga antigua, rocín flaco y
galgo corredor.\n

Inventario en formato YAML

A partir de la versión 2.4 de Ansible es posible definir el inventario en formato


YAML y no solo en formato INI. Un ejemplo se muestra a continuación:

webs:
hosts:
www.oforte.net:
www3.oforte.net:
vars:
entorno: prod
ansible_user: agonzalez

Desafortunadamente un inventario con grupos que contienen a su vez otros


grupos, el formato en YAML es más complicado que usando formato INI:

20 © Alfaomega-RC Libros
CAPÍTULO 3: PRIMEROS PASOS

all:
children:
oforte:
children:
webs:
hosts:
www.oforte.net:
www3.oforte.net:
backup:
hosts:
backup.oforte.net:
backup2.oforte.net:
vars:
http_port: 80

Inventario dinámico

Un inventario dinámico es una lista de nodos a administrar que varía durante


el tiempo y no es necesario editarlo manualmente en ficheros. Esta lista se puede
obtener desde las siguientes fuentes:

● Desde un proveedor Cloud, ejemplos:


○ Amazon Web Services
○ Google Cloud Platform
○ Azure
○ DigitalOcean
● Infraestructura propia, ejemplos:
○ OpenStack
○ Ovirt
○ OpenShift
○ Zabbix
● Un script propio que genere la lista de nodos a manejar. Este script se
puede conectar a un CMDB o a una base de datos que contenga dicha lista.

El repositorio que contiene los scripts a utilizar para el inventario dinámico se


encuentra en el repositorio oficial de Ansible:
https://github.com/ansible/ansible/tree/devel/contrib/inventory

© Alfaomega-RC Libros 21
ANSIBLE

Contiene scripts con terminación .py y un fichero de configuración con


terminación .ini para definir los parámetros de conexión y autenticación. Un
ejemplo es utilizando el proveedor Digital Ocean:

digital_ocean.ini
# Ansible DigitalOcean external inventory script settings
[digital_ocean]
api_token = f3938d5154a35588d8573f97c93e9aa8c119bf5695abd0
cache_path = /tmp
cache_max_age = 300
use_private_network = False
group_variables = {}

Podemos ejecutar manualmente el script para comprobar que la api_token es


correcta y podemos listar los droplets, este script devuelva la información en
formato JSON (JavaScript Object Notation):

# python digital_ocean.py
{"droplets": [{"status": "active", "kernel": {"version":
"2016.07.13-DigitalOcean_loader_Ubuntu", "id": 7515,
"name": "DigitalOcean GrubLoader v0.2 (20160714)"},
"volume_ids": [], "locked": false, "name":
"users.oforte.net", "backup_ids": [], "created_at": "2014-
02-12T12:19:12Z", "snapshot_ids": [], "size_slug": "512mb",
"networks": {"v4": [{"type": "public", "netmask":
"255.255.255.0", "ip_address": "95.85.59.73", "gateway":
"95.85.59.1"}, {"type": "private", "netmask":
"255.255.0.0", "ip_address": "10.129.236.42", "gateway":
"10.129.0.1"}], "v6": []}, "next_backup_window": null,
"vcpus": 1, […]

22 © Alfaomega-RC Libros
CAPÍTULO 3: PRIMEROS PASOS

Al igual que un inventario estático, podemos utilizar la opción --inventory [-i]


para llamar al script que nos listará los nodos, utilizando el mismo proveedor
vemos la lista de servidores a continuación:

# ansible -i ./digital_ocean.py all --list-hosts


hosts (2):
95.85.59.73
37.139.7.43
# ansible -i ./digital_ocean.py all -m ping
37.139.7.43 | SUCCESS => {
"changed": false,
"ping": "pong"
}
95.85.59.73 | SUCCESS => {
"changed": false,
"ping": "pong"
}

Los inventarios dinámicos también agrupan los servidores en diferentes


grupos, dependiendo del proveedor. Veamos un ejemplo para Digital Ocean que
los agrupa por distribución, por tamaño o región:

# ansible -i ./digital_ocean.py size_1gb -m ping


37.139.7.43 | SUCCESS => {
"changed": false,
"ping": "pong"
}
# ansible -i ./digital_ocean.py distro_Ubuntu -m ping
95.85.59.73 | SUCCESS => {
"changed": false,
"ping": "pong"
}

La importancia de tener un inventario dinámico es que ante cualquier creación


de un servidor en un proveedor, automáticamente las tareas de automatización
definidas se ejecutarán en él.

Para Google Cloud Platform la configuración de gce.py es similar a la siguiente:

gce.ini
[gce]
libcloud_secrets =

© Alfaomega-RC Libros 23
ANSIBLE

gce_service_account_email_address = ansible@oforte-
196215.iam.gserviceaccount.com
gce_service_account_pem_file_path = /root/oforte.pem
gce_project_id = oforte-196215
gce_zone =
[inventory]
inventory_ip_type =
[cache]
cache_path = ~/.ansible/tmp
cache_max_age = 300

Para el uso de gce.py necesitamos instalar libcloud (en Debian/Ubuntu: apt-get


install python-libcloud, en CentOS/RHEL: yum install python2-libcloud), ejemplo:

# ansible all -i ./gce.py --list-hosts


hosts (4):
centos01
centos02
debian02
debian01
# ansible europe-west1-b -i ./gce.py --list-hosts
hosts (1):
debian02

En el caso de Amazon Web Services:

ec2.ini
[ec2]
regions = all
regions_exclude = us-gov-west-1, cn-north-1
destination_variable = public_dns_name
vpc_destination_variable = ip_address
route53 = False
all_instances = False

[credentials]
aws_access_key_id = AKIAJW33G62O45YATHMA
aws_secret_access_key = sumvlXVT5gBae9RTeCwjsY6UY3

Al igual que los otros inventarios dinámicos es el mismo funcionamiento:

24 © Alfaomega-RC Libros
CAPÍTULO 3: PRIMEROS PASOS

# ansible all -i ./ec2.py --list-hosts


hosts (2):
18.197.46.199
18.197.74.143
# ansible eu-central-1 -i ./ec2.py --list-hosts
hosts (1):
18.197.46.199

Combinar inventarios
Es posible utilizar más de un inventario, combinándolos para crear una lista de
nodos a administrar y también los grupos de ambos. Para ello en la opción --
inventory [-i] indicaremos un directorio que contiene los inventarios, ya sean
estáticos como dinámicos. Combinar inventarios es de gran utilidad para entornos
de Hybrid Cloud. Todos los ficheros dentro de dicho directorio serán utilizados
como inventario excepto que posean una de estas extensiones (configurable con
la opción inventory_ignore_extensions en ansible.cfg):

~, .orig, .bak, .ini, .cfg, .retry, .pyc, .pyo

En el siguiente ejemplo, el directorio inventario contiene 4 inventarios, de los


cuales 3 son dinámicos (ec2.py, gce.py, digital_ocean.py) y uno estático
(servidores_oforte).

# ansible -i inventario/ all --list-hosts


hosts (13):
www.oforte.net |
cloud.oforte.net |- Nodos del fichero servidores_oforte
lab.oforte.net |
95.85.59.73 |_ Servidores Digital Ocean
37.139.7.43 |
34.245.119.134 |- Servidores AWS
18.197.46.199 |
centos02 |
centos01 |- Servidores en GCE
debian01 |
debian02 |

En un inventario combinado también es posible usar los subdirectorios


host_vars y group_vars, para definir los parámetros de conexión y variables tanto
para nodos y grupos.

© Alfaomega-RC Libros 25
ANSIBLE

Desde un inventario se puede hacer referencia a otro inventario, por ejemplo


si en el inventario estático queremos incluir servidores de un proveedor cloud
para crear un grupo. Ejemplo:

inventario/servidores_oforte
cloud.oforte.net
lab.oforte.net
[debian]
www.oforte.net
debian01
debian02
# ansible -i inventario/ debian --list-hosts
hosts (3):
www.oforte.net
debian01
debian02

En el ejemplo anterior, debian01 y debian02 son servidores dentro del


proveedor Google Cloud Platform y los incluimos dentro de un grupo llamado
debian en el inventario estático.

Ansible en modo Ad-Hoc


El modo ad-hoc permite a través de la línea de comandos comprobar la
conexión a los nodos o realizar una tarea en ellos. Esta tarea a ejecutar no se
guarda en un fichero ni se lee de un fichero. Ya hemos visto que a través de la
opción "-m ping" se comprobaba la conexión, o a través de la opción "-a
comando" para ejecutar un comando en cada uno de ellos. Sintaxis:

ansible [opciones] servidores|grupo|all|ungrouped [-m


modulo] [-a argumentos]

Un módulo realiza una tarea dentro del nodo a administrar, algunos ejemplos:

● El módulo copy copia un fichero desde donde ejecutamos ansible al nodo


administrado.
● El módulo command o shell ejecuta comandos en dicho servidor.
● El módulo yum o apt administra paquetes dentro del gestor.

26 © Alfaomega-RC Libros
CAPÍTULO 3: PRIMEROS PASOS

Ejemplos:

# ansible all -i ./gce.py -u alberto --become -m copy -a


"src=/etc/resolv.conf dest=/etc/resolv.conf"

debian02 | SUCCESS => {


"changed": true,
"checksum": "4676823f5982023c9b7a9a4a3ee1678bbfaa3c9b",
"dest": "/etc/resolv.conf",
"gid": 0,
"group": "root",
"md5sum": "a657efa732c738125e90d495d9625da0",
"mode": "0644",
"owner": "root",
"size": 62,
"src": "/home/alberto/.ansible/tmp/ansible-tmp-1519493868.68-
183890513113842/source",
"state": "file",
"uid": 0
}
debian01 | SUCCESS => {
"changed": true,
"checksum": "4676823f5982023c9b7a9a4a3ee1678bbfaa3c9b",
"dest": "/etc/resolv.conf",
"gid": 0,
"group": "root",
"md5sum": "a657efa732c738125e90d495d9625da0",
"mode": "0644",
"owner": "root",
"size": 62,
"src": "/home/alberto/.ansible/tmp/ansible-tmp-1519493868.83-
134214750887314/source",
"state": "file",
"uid": 0
}
centos01 | SUCCESS => {
"changed": true,
"checksum": "4676823f5982023c9b7a9a4a3ee1678bbfaa3c9b",
"dest": "/etc/resolv.conf",
"gid": 0,
"group": "root",
"md5sum": "a657efa732c738125e90d495d9625da0",
"mode": "0644",
"owner": "root",
"secontext": "system_u:object_r:net_conf_t:s0",

© Alfaomega-RC Libros 27
ANSIBLE

"size": 62,
"src": "/home/alberto/.ansible/tmp/ansible-tmp-1519493870.36-
271590123807833/source",
"state": "file",
"uid": 0
}
centos02 | SUCCESS => {
"changed": true,
"checksum": "4676823f5982023c9b7a9a4a3ee1678bbfaa3c9b",
"dest": "/etc/resolv.conf",
"gid": 0,
"group": "root",
"md5sum": "a657efa732c738125e90d495d9625da0",
"mode": "0644",
"owner": "root",
"secontext": "system_u:object_r:net_conf_t:s0",
"size": 62,
"src": "/home/alberto/.ansible/tmp/ansible-tmp-1519493871.21-
201585933776831/source",
"state": "file",
"uid": 0
}

En este ejemplo se ha copiado el fichero /etc/resolv.conf (definido en src=) a


cuatro nodos (debian01, debian02, centos01 y centos2) en el mismo lugar
(definido en dest=) y el color naranja del texto indica que el fichero ha sido
copiado, ya que el contenido del fichero donde ejecutamos ansible difiere del
contenido de los ficheros de los nodos. Al volver a ejecutarlo veremos que el
fichero destino no se ha modificado y se muestra en color verde.

# ansible all -i ./gce.py –u alberto --become -m copy -a


"src=/etc/resolv.conf dest=/etc/resolv.conf"

debian02 | SUCCESS => {


"changed": false,
"checksum": "4676823f5982023c9b7a9a4a3ee1678bbfaa3c9b",
"dest": "/etc/resolv.conf",
"gid": 0,
"group": "root",
"mode": "0644",
"owner": "root",
"path": "/etc/resolv.conf",
"size": 62,

28 © Alfaomega-RC Libros
CAPÍTULO 3: PRIMEROS PASOS

"state": "file",
"uid": 0
}
(omitido)

Podemos instalar, si no está instalado, o actualizar un paquete dentro de los


nodos. También es posible eliminar una aplicación en los mismos. En este ejemplo
se utiliza la opción --limit con los nodos, separados por comas, para limitar los
nodos a usar:

# ansible all --limit centos01,centos02 -i ./gce.py --user


alberto --become -m yum -a "name=lftp state=present"

centos01 | SUCCESS => {


"changed": true,
"msg": "",
"rc": 0,
"results": [
"(omitido) \nInstalled:\n lftp.x86_64 0:4.4.8-8.el7_3.2
\n\nComplete!\n"
]
}
centos02 | SUCCESS => {
"changed": true,
"msg": "",
"rc": 0,
"results": [
"(omitido) \nInstalled:\n lftp.x86_64 0:4.4.8-8.el7_3.2
\n\nComplete!\n"
]
}

En el siguiente ejemplo, eliminamos el paquete "vim" de los servidores (se


muestra en naranja en caso de eliminarlo). En vez de utilizar --limit con el grupo
all, en este caso utilizamos "debian*" para todos los servidores que empiezan por
la palabra debian. También podríamos utilizar "debian01:debian02" para limitarlo
solo a dos servidores.

# ansible debian* -i ./gce.py -u alberto --become -m apt -a


"name=vim state=absent"

debian01 | SUCCESS => {


"changed": true,

© Alfaomega-RC Libros 29
ANSIBLE

"stderr": "",
"stdout": "(omitido)",
"stdout_lines": [ (omitido) ]
}
debian02 | SUCCESS => {
"changed": true,
"stderr": "",
"stdout": "(omitido)",
"stdout_lines": [ (omitido) ]
}

Si está eliminado, se nos mostrará en verde y la palabra SUCCESS:

# ansible debian01:debian02 -i ./gce.py --user alberto --


become -m apt -a "name=vim state=absent"

debian02 | SUCCESS => {


"changed": false
}
debian01 | SUCCESS => {
"changed": false
}

En caso de no tener permisos o si hay un error de sintaxis se mostrará en rojo


el error, en el siguiente ejemplo no indicamos la opción --become de escalar de
permisos:

# ansible debian01 -i ./gce.py -u alberto -m apt -a


"name=vim state=present"

debian01 | FAILED! => {


"cache_update_time": 1519495436,
"cache_updated": false,
"changed": false,
"failed": true,
"msg": "'/usr/bin/apt-get -y -o \"Dpkg::Options::=--force-
confdef\" -o \"Dpkg::Options::=--force-confold\" install
'vim'' failed: E: Could not open lock file
/var/lib/dpkg/lock - open (13: Permission denied)\nE:
Unable to lock the administration directory
(/var/lib/dpkg/), are you root?\n",
"stderr": "E: Could not open lock file /var/lib/dpkg/lock
- open (13: Permission denied)\nE: Unable to lock the

30 © Alfaomega-RC Libros
CAPÍTULO 3: PRIMEROS PASOS

administration directory (/var/lib/dpkg/), are you


root?\n",
"stdout": "",
"stdout_lines": []
}

El módulo setup sirve para obtener información del nodo, como puede ser la
versión del sistema operativo, la memoria total, las direcciones IP entre otra gran
cantidad de información útil.

# ansible debian01 -i ./gce.py --user alberto -m setup

debian01 | SUCCESS => {


"ansible_facts": {
"ansible_all_ipv4_addresses": [
"10.164.0.2"
],
"ansible_all_ipv6_addresses": [
"fe80::4001:aff:fea4:2"
],
"ansible_architecture": "x86_64",
(omitido)
"ansible_distribution": "Debian",
"ansible_distribution_major_version": "9",
"ansible_distribution_release": "stretch",
"ansible_distribution_version": "9.3",
"ansible_dns": {
"nameservers": [
"8.8.8.8"
]
},
"ansible_domain": "c.oforte-196215.internal",
(omitido)
"ansible_memory_mb": {
"nocache": {
"free": 3574,
"used": 130
},
"real": {
"free": 3315,
"total": 3704,
"used": 389
},
"swap": {

© Alfaomega-RC Libros 31
ANSIBLE

"cached": 0,
"free": 0,
"total": 0,
"used": 0
}
},
"ansible_memtotal_mb": 3704,
(omitido)
"ansible_processor_cores": 1,
"ansible_processor_count": 1,
},
"changed": false
}

Configuración
El fichero de configuración global contiene opciones diversas para el
funcionamiento de Ansible:

Sección Descripción
[defaults] Valores por defecto generales
[privilege_escalation] Configuración para escalar permisos
[ssh_connection] Opciones de OpenSSH
[selinux] Opciones para SELinux
[colors] Colores

El orden de búsqueda para el fichero de configuración es el siguiente:

● Variable de entorno: ANSIBLE_CONFIG.


● Fichero ansible.cfg en el directorio actual.
● Fichero .ansible.cfg en el directorio del usuario.
● Fichero /etc/ansible/ansible.cfg

Las opciones más comunes que se pueden especificar y los valores por defecto
se indican en la siguiente tabla:

32 © Alfaomega-RC Libros
CAPÍTULO 3: PRIMEROS PASOS

Configuraciones generales por defecto


Opción Valor por defecto Descripción
inventory /etc/ansible/hosts Ubicación por defecto del
fichero de inventario,
script, o directorio que
será utilizado para
determinar los nodos a
administrar.
forks 5 Número de procesos en
paralelo a utilizar para
comunicar con los nodos
remotos.
remote_port 22 Puerto por defecto a
utilizar cuando gestionamos
un nodo por SSH.
host_key_check True Si un nodo administrado es
ing reinstalado y tiene una
clave distinta en el
fichero known_hosts,
causará error si esta
opción está habilitada.
module_name command El módulo por defecto a
utilizar cuando no se
especifica opción -m al
comando ansible.
timeout 10
El tiempo de espera por
defecto cuando se intenta
conectar a un nodo por SSH.
remote_user root
Usuario por defecto a
utilizar cuando se conecta
a los nodos usando ansible-
playbook. El comando
ansible utilizará el mismo
nombre de usuario actual
que ejecuta la tarea.
inventory_igno ~, .orig, .bak, Controla qué ficheros se
re_extensions .ini, .cfg, ignorarán cuando se utiliza
.retry, .pyc, .pyo un directorio como
inventario.

© Alfaomega-RC Libros 33
ANSIBLE

Configuración por defecto sobre escalar permisos


Opción Por defecto Descripción
become false Define si activar la escalada
de permisos.
become_method sudo Especifica el método de
escalada de permisos.
Opciones: sudo, su, pbrun,
pfexec, doas, ksu.
become_user root Indica el usuario que se
utilizará para la escalada de
permisos.
become_ask_pass False Indica si se debe preguntar
por la contraseña de escalada
de permisos.
Opciones para OpenSSH
Opción Valor por defecto Descripción
ssh_args -o ControlMaster=auto Argumentos a utilizar
-o ControlPersist=60s cuando se conecta a un
nodo a través de SSH.
control_path %(directory)s/ansible- Ubicación para guardar
ssh-%%h-%%p-%%r los ficheros ControlPath
sockets.
control_path_dir ~/.ansible/cp El directorio base para
los ficheros ControlPath
sockets.
scp_if_ssh False Opción para habilitar
SCP en caso de que SFTP
no esté disponible.
pipelining False
Esta opción reduce el
número de operaciones
SSH necesarias para
ejecutar un módulo en un
nodo remoto. Mejora el
rendimiento pero puede
causar problemas si la
opción requiretty está
habilitada en el fichero
sudoers del nodo remoto.

34 © Alfaomega-RC Libros
CAPÍTULO 3: PRIMEROS PASOS

ssh_executable ssh Ubicación del binario de


programa ssh.
Opciones para SELinux
Opción Valor por defecto Descripción
special_context_ nfs,vboxsf,fuse,ram Lista de sistemas de
filesystems fs,myspecialfs ficheros que requieren
un trato especial cuando
tratamos con contextos
de seguridad.
Opciones sobre colores
Opción Valor por defecto Descripción
error red Color del texto cuando una tarea
da error.
changed yellow Color del texto cuando la tarea
hace modificaciones en el nodo
administrado.
ok green Color del texto cuando una tarea
no hace modificaciones.

Windows
Como se indicaba en la introducción, es posible administrar servidores de
Windows. Al contrario que con los servidores Linux, donde el acceso se realiza por
SSH y no es requerido configurar nada, para Windows debemos hacer algunas
tareas previas:

En el servidor que estamos ejecutando ansible:

● Instalar pywinrm:
○ CentOS/RHEL: yum install python2-winrm
○ Otras distribuciones: pip install pywinrm
● Especificar al nodo Windows a administrar el parámetro de conexión:
○ ansible_connection=winrm
● Ignorar la comprobación del certificado:
○ ansible_winrm_server_cert_validation=ignore

En el servidor Windows a administrar:

● Tener instalado PowerShell 3.0 o superior.

© Alfaomega-RC Libros 35
ANSIBLE

● Ejecutar el siguiente script de PowerShell para habilitar el control remoto:


https://github.com/ansible/ansible/blob/devel/examples/scripts/ConfigureRe
motingForAnsible.ps1
● Habilitar en el firewall el puerto 5986.

Fichero de inventario (todo en una línea):

windows01 ansible_host=35.196.191.155
ansible_connection=winrm
ansible_winrm_server_cert_validation=ignore

Comprobar conexión al servidor Windows utilizando -m win_ping

# ansible -i windows -u alberto -k all -m win_ping


SSH password:
windows01 | SUCCESS => {
"changed": false,
"failed": false,
"ping": "pong"
}
# ansible -i windows -u alberto -k all -m setup|grep -i
ansible_os_name

SSH password:
"ansible_os_name": "Microsoft Windows Server 2016
Datacenter",

36 © Alfaomega-RC Libros
PLAYBOOKS

INTRODUCCIÓN

Un playbook (libro de jugadas) contiene una lista de plays (jugadas) a realizar.


Estos plays definen los nodos a administrar y una lista de tasks (tareas) a realizar
dentro de ellos. Un playbook contiene al menos un play, y cada play contiene al
menos una tarea a ejecutar y puede definir diferentes parámetros de conexión,
configuraciones y variables.

El formato usado para definir todos estos elementos es YAML. Veamos un


ejemplo simple de un playbook incluyendo un play.

---
- name: Mi primer playbook
hosts: debian
tasks:
- name: Copiar fichero a los servidores
copy: src=sources.list dest=/etc/apt/sources.list
...

En el ejemplo anterior:

● Se define un play con nombre (es opcional pero recomendado especificar


el nombre con la clave name): Mi primer playbook.
● Se ejecutará en el servidor llamado debian o los nodos dentro del grupo
llamado debian. Esta clave (hosts) es obligatoria.
ANSIBLE

● A continuación se define una lista de tareas (clave tasks) a ejecutar:


○ La primera tarea contiene un nombre (al igual que el nombre del
play, los nombres de las tareas son opcionales pero recomendados):
"Copiar ficheros a los servidores"
○ La tarea a realizar es copiar un fichero (utilizando el módulo copy):
el fichero sources.list (src=) en el directorio actual a los nodos dentro
de /etc/apt/sources.list (dest=)

La misma tarea se puede escribir de la siguiente manera (más legible en caso


de cadenas de texto largas):

- name: Copiar fichero a los servidores


copy:
src: sources.list
dest: /etc/apt/sources.list

Un playbook puede contener diferentes plays que pueden conectarse a


diferentes servidores y realizar diferentes tareas. En el siguiente ejemplo se
definen 2 plays, el primero para servidores dentro del grupo debian y el segundo
para nodos para el grupo centos:

---
- name: Conectar a los servidores Debian
hosts: debian
tasks:
- name: Copiar fichero a los servidores
copy: src=sources.list dest=/etc/apt/sources.list
- name: Conectar a los servidores CentOS
hosts: centos
tasks:
- name: Copiar fichero a los servidores
copy: src=cntos.repo dest=/etc/yum.repos.d/centos.repo
...

Un play puede definir parámetros de conexión y variables a ser utilizadas


dentro de las tareas. El orden de cómo indiquemos los valores puede ser como el
usuario quiera siempre que se mantenga la indentación que se muestra a
continuación:

---
- name: Mi primer playbook
hosts: debian

38 © Alfaomega-RC Libros
CAPÍTULO 4: PLAYBOOKS

remote_user: alberto
become: True
vars:
entorno: produccion
tasks:
- name: Copiar fichero a los servidores
copy: src=sources.list dest=/etc/apt/sources.list
...

Para ejecutar un playbook se utiliza el comando ansible-playbook que posee


las mismas opciones que el comando ansible pero que requiere como argumento
un fichero (normalmente con terminación .yml o .yaml) que contiene los plays.

Listar los nodos donde se realizarán las tareas.


# ansible-playbook -i inventario/ --list-hosts sources.yml
playbook: copiar_sources.yml
play #1 (debian): Mi primer playbook TAGS: []
pattern: [u'debian']
hosts (2):
debian02
debian01
Ejecutar el playbook.
# ansible-playbook -i inventario/ copiar_sources.yml
PLAY [Mi primer playbook] *****************
TASK [Gathering Facts] ****
ok: [debian01]
ok: [debian02
TASK [Copiar fichero a los servidores] ****
changed: [debian02]
changed: [debian01]
PLAY RECAP ****************
debian01 : ok=2 changed=1 unreachable=0 failed=0
debian02 : ok=2 changed=1 unreachable=0 failed=0

El resultado de ansible-playbook nos mostrará por cada una de las tareas el


resultado: si no se ha cambiado nada (ok), si se ha modificado algo (changed), si
ha fallado (failed) o si la tarea ha sido omitida (skipped, se explicarán las
condiciones más adelante). Además, se mostrará un resumen final (PLAY RECAP):
cuántas tareas se han ejecutado (ok=), cuántas tareas se han modificado
(changed=), cuántas tareas no han podido ser ejecutadas por no ser posible
conectarse (unreachable=) y cuántas tareas han fallado (failed=).

© Alfaomega-RC Libros 39
ANSIBLE

Cuando ejecutamos un playbook, la primera tarea para cada uno de los plays
es conectarse a los servidores y obtener la información de cada uno de los nodos
(igual que el módulo setup que indicamos en el apartado de Ad-Hoc). En el caso
de no querer obtener esa información y querer acelerar el proceso de ejecución
es posible incluir al play la siguiente línea:

---
- name: Mi primer playbook
hosts: debian
gather_facts: False
[...]

Algunos valores importantes:

● remote_user: indica el usuario con el que conectarse.


● become: indica si escalar permisos.
● become_user: el usuario al que escalar el permiso (p.e. root).
● become_method: el método a utilizar para escalar permisos (p.e. sudo).
● check_mode: si el playbook solo comprobará sin hacer modificaciones.

Patrones
En la lista de nodos a utilizar podemos especificar un servidor o un grupo de
servidores. Además, podemos utilizar el asterisco (*) como comodín. Pero
también podemos indicar varios nodos y varios grupos separados por coma o por
dos puntos, esto funciona como un OR (lista que esté en un grupo o en otro):

hosts: grupo1:grupo2:grupo3 hosts: grupo1,grupo2,grupo3


hosts: servidor1:servidor2 hosts: servidor1,servidor2

Para excluir los nodos de un grupo, utilizaremos el carácter especial "!".


Ejemplo:

hosts: all:!grupo hosts: grupo:!nodo hosts: grupo:!nombr*

En el caso de querer solo trabajar en los nodos que pertenece a dos grupos,
utilizaremos el carácter especial "&". Ejemplos:

hosts: grupo1:&grupo2 hosts: grupo1:grupo2:&grupo3

40 © Alfaomega-RC Libros
CAPÍTULO 4: PLAYBOOKS

Opciones ansible-playbook
Hemos visto que las opciones para ansible-playbook son muy similares a las
que hemos visto del comando ansible (--inventory, --limit, --list-hosts) pero
ansible-playbook incluye otras opciones útiles cuando trabajamos con playbooks:

Opción Descripción
--syntax-check Comprueba la sintaxis del playbook y de los
ficheros adicionales que son incluidos.
--check [-C] Ejecuta el playbook en modo "comprobar".
Realizará las tareas pero no hará cambios
en el servidor.
--lists-tasks Lista todas las tareas dentro del playbook.
--step Pregunta por cada tarea que hacer: si
ejecutarla o no. Además permite continuar y
ejecutar el resto de tareas sin preguntar.
--start-at-task Inicia el playbook en la tarea especificada
-v, --verbose Activa el modo de mostrar más información.
Con -vvv (3) muestra más información y con
-vvvv (4) muestra información detallada de
la conexión.

Variables
Una variable contiene un valor modificable para dinamizar las tareas, algunos
de sus posibles usos se listan a continuación:

● Definir un puerto de una aplicación. Por ejemplo: el puerto 443 para un


servidor web.
● Indicar el usuario que será utilizado. Por ejemplo: el usuario www-data o
apache2 para el servidor web.
● Establecer la ruta de un fichero de configuración. Por ejemplo:
/etc/http/httpd.conf

Las variables pueden ser definidas automáticamente a través de los facts


(información obtenida del nodo que se administrará) o manualmente:

● En los plays, roles o ficheros de variable, entre otros elementos.


● A través de la opción --extra-vars [-e]

© Alfaomega-RC Libros 41
ANSIBLE

Esas variables pueden ser utilizadas tanto en los plays, como en las tareas y en
las plantillas. Además podrán ser usadas en condiciones y en bucles.

Las variables dentro de las plantillas son referidas con la siguiente sintaxis:

{{ nombre_variable }}

Para definir variables dentro de un play utilizaremos la siguiente sintaxis:

---
- hosts: localhost
vars:
mivariable: "Valor"
milista:
- "Valor lista 1"
- "Valor lista 2"
- "Valor lista 3"
tasks:
- name: Mostrar el valor de mivariable
debug: var=mivariable
- name: Mostrar el valor de milista
debug: msg="Elementos de la lista, {{ milista }}"
...

El módulo debug permite mostrar el valor de las variables; acepta dos


opciones:

Opción Descripción
var=variable Muestra el valor de la variable especificada.
msg="Texto" Muestra el texto especificado y es posible
mostrar variables.
verbosity=num Controla cuándo mostrar el mensaje, de 1 (-v)
a 3 (-vvv o más).

Al ejecutar este playbook se muestra el valor de las variables definidas dentro


del fichero.

# ansible-playbook variables.yml
PLAY [localhost] **********
TASK [Gathering Facts] ****
ok: [localhost]

42 © Alfaomega-RC Libros
CAPÍTULO 4: PLAYBOOKS

TASK [Mostrar el valor de mivariable] *****


ok: [localhost] => {
"mivariable": "Valor"
}
TASK [Mostrar el valor de milista] ********ok: [localhost]
=> {
"msg": "Elementos de la lista, [u'Valor lista 1', u'Valor
lista 2', u'Valor lista 3']"
}
PLAY RECAP ****************
localhost : ok=3 changed=0 unreachable=0 failed=0

Utilizando la opción --extra-vars sobrescribiremos el valor definido y se


utilizará el especificado, ya que especificando las variables con dicha opción
tendrá precedencia sobre cualquier variable definida dentro de los playbook.

# ansible-playbook --extra-vars "mivariable='Variable de


extra vars'" variables.yml

[...]
TASK [Mostrar el valor de mivariable] *****
ok: [localhost] => {
"mivariable": "Variable de extra vars"
}
[..]

Handlers
Un handler es una tarea que solo se ejecutará en caso de que otra tarea le
llame. El uso más común es reiniciar un servicio en un handler cuando la
configuración es cambiada en una tarea.

Para definir un handler definiremos una tarea dentro de la sección handlers y


utilizaremos la expresión notify para hacer referencia a él. Una de las ventajas de
estas tareas es que se ejecutarán al final del playbook y si varias tareas llaman al
mismo handler solo se ejecutará una vez (en el caso de reiniciar un servicio,
aunque varias tareas llamen a reiniciar el servicio, solo se realizará una vez al final
del playbook).

---
- name: Copiar el fichero sshd_config
hosts: servidor

© Alfaomega-RC Libros 43
ANSIBLE

tasks:
- name: Copiar configuración
copy: src=sshd_config dest=/etc/ssh/sshd_config
notify: restart_sshd
handlers:
- name: restart_sshd
service: name=sshd state=restarted...

Si el fichero que copiamos modifica el destino, entonces la tarea de reinicio del


servidor será llamada.

# ansible-playbook sshd.yml
PLAY [Copiar el fichero sshd_config] ******
TASK [Gathering Facts] ****
ok: [servidor]
TASK [Copiar configuracion] ***************
changed: [servidor]
RUNNING HANDLER [restart_sshd] ************
changed: [servidor]

PLAY RECAP ****************servidor: ok=3 changed=2


unreachable=0 failed=0

En caso de que el fichero coincida con el destino y no se realice ninguna


modificación, la tarea definida en el handler no será ejecutada.

# ansible-playbook sshd.yml
PLAY [Copiar el fichero sshd_config] ******
TASK [Gathering Facts] ****
ok: [servidor]
TASK [Copiar configuración] ***************
ok: [servidor]

PLAY RECAP ****************


servidor: ok=2 changed=0 unreachable=0 failed=0

Desde la versión 2.2 de Ansible, es posible llamar a varias tareas utilizando


notify. Para ello las tareas dentro de handlers utilizarán la expresión listen.

---
- name: Copiar el fichero sshd_config
hosts: servidor

44 © Alfaomega-RC Libros
CAPÍTULO 4: PLAYBOOKS

tasks:
- name: Copiar configuración
copy: src=sshd_config dest=/etc/ssh/sshd_config
notify: "reiniciar servicios sshd"
handlers:
- name: Reiniciar sshd
service: name=sshd state=restarted
listen: "reiniciar servicios sshd"
- name: Reiniciar autofs
service: name=autofs state=restarted
listen: "reiniciar servicios sshd"
...

Al ejecutar el playbook anterior, si el fichero de configuración es modificado


serán ejecutadas las tareas con el listen "reiniciar servicios sshd".

# ansible-playbook sshd.yml
PLAY [Copiar el fichero sshd_config] ******
TASK [Gathering Facts] ****
ok: [servidor]
TASK [Copiar configuración] ***************
changed: [servidor]
RUNNING HANDLER [Reiniciar sshd] **********
changed: [servidor]
RUNNING HANDLER [Reiniciar autofs] ********
changed: [servidor]

PLAY RECAP ****************


servidor : ok=4 changed=3 unreachable=0 failed=0

Include e import
Es posible dividir un playbook en distintas partes para facilitar su edición y
tratado. A partir de la versión 2.4 es posible incluir ficheros de forma estática
(import) o de forma dinámica (include). Para incluir ficheros que contienen plays o
tareas, utilizaremos las siguientes expresiones:

include: fichero.yml Incluye un fichero que contiene un


Play (si es llamado desde un
playbook) o tareas. Obsoleta desde
la versión Ansible 2.4.

© Alfaomega-RC Libros 45
ANSIBLE

import_playbook: playbook.yml Incluye desde un fichero de


playbooks maestro un fichero de
playbook externo.
import_tasks: tareas.yml Incluye de forma estática una
lista de tareas.
include_tasks: tareas.yml Incluye de forma dinámica una
lista de tareas.
vars_files: La sintaxis vars_files permite
- variables.yml incluir uno o varios ficheros
donde están las variables
definidas. Esta sintaxis es a
nivel de Playbook.
include_vars: variables.yml Lee el fichero indicado para
establecer las variables.

En el siguiente ejemplo se muestra el uso de las expresiones anteriormente


explicadas.

instalar.yml (Playbook maestro)


---
- import_playbook: play_apache.yml
- import_playbook: play_mysql.yml
...
play_apache.yml (Playbook para instalar Apache)
---
- hosts: servidor
name: Instalar Apache
vars_files:
- vars_apache.yml
tasks:
- import_tasks: tareas_apache.yml
...
vars_apache.yml (Fichero con variables)
---
paquete: apache2
...
tareas_apache.yml (Tareas para instalar Apache)
---
- name: Instalar el paquete especificado

46 © Alfaomega-RC Libros
CAPÍTULO 4: PLAYBOOKS

apt: name="{{ paquete }}" state=present


...
play_mysql.yml (Play para instalar MySQL)
---
- hosts: servidor
name: Instalar MySQL
tasks:
- include_vars: vars_mysql.yml
- include_tasks: tareas_mysql.yml
...
vars_mysql.yml (Variables para MySQL)
---
version: "5.5"
...
tareas_mysql.yml (Tareas para instalar MySQL)
---
- name: Instalar la versión especificada
apt: name="mysql-server-{{ version }}" state=present
...

Ejecutando el playbook maestro (instalar.yml) hará las siguientes tareas:

● Incluye el fichero que contiene un playbook: play_apache.yml, que a su


vez:
○ Incluye el fichero de variables vars_apache.yml
- Define la variable "paquete" con el nombre del software a instalar.
- Importa las tareas del fichero tareas_apache.yml
- Instala el software definido en la variable "paquete"
● Incluye el fichero que contiene un playbook: play_mysql, que a su vez:
○ Incluye el fichero de variables vars_mysql.yml
- Define la variable "version" con la versión a instalar.
○ Importa las tareas del fichero tareas_mysql.yml
- Instala el software usando la versión definida en la variable.

Ejecutar el playbook maestro incluirá los demás playbooks.

# ansible-playbook instalar.yml
PLAY [Instalar Apache] ****
TASK [Gathering Facts] ****
ok: [servidor]

© Alfaomega-RC Libros 47
ANSIBLE

TASK [Instalar el paquete especificado] ***


ok: [servidor]
PLAY [Instalar MySQL] *****
TASK [include_vars] *******
ok: [servidor]
TASK [include_tasks] ******
included: /tmp/tareas_mysql.yml for localhost
TASK [Instalar la version especificada] ***
ok: [servidor]

PLAY RECAP ****************


servidor: ok=6 changed=0 unreachable=0 failed=0

Es posible pasar variables cuando incluimos ficheros de tareas como se


muestra a continuación:

- import_tasks: tareas_apache.yml paquete=apache2


- include_tasks: tareas_mysql.yml
vars:
puerto: 3306
bbdd:
- web1
- app2

Al igual que dentro de tasks podemos utilizar import_tasks e include_tasks


dentro de la sección de handlers.

play_mysql.yml
---
- hosts: servidor
name: Instalar MySQL
tasks:
- include_vars: vars_mysql.yml
- include_tasks: tareas_mysql.yml
vars:
puerto: 3306
bbdd:
- web1
- app2
handlers:
- include_tasks: handlers_mysql.yml
...

48 © Alfaomega-RC Libros
CAPÍTULO 4: PLAYBOOKS

handlers_mysql.yml
---
- name: Reiniciar MySQL
service: name=mysqld state=restarted
...

Prioridad variables
Hemos visto que hay diferentes maneras de definir variables y en diferentes
lugares donde hacerlo, desde la configuración del Play hasta variables dentro del
rol. En esta sección indicaremos qué variables tienen precedencia sobre las otras,
de menor precedencia a mayor:

1. "Defaults" variables definidas en un rol.


2. Variables de grupo
a. Variables de grupo en el inventario
b. Variables definidas en group_vars/all
c. Variables definidas en group_vars/nombregrupo
3. Variables de servidor:
a. Variables definidas en el inventario
b. Variables definidas en host_vars/nombrehost
4. "Facts" del servidor
5. Variables del Play
a. vars_prompt
b. vars_files
6. Variables del role, definidas en roles/nombrerol/vars/main.yml
7. Variables de bloque
8. Variables de la tarea
9. Parámetros role (y de include_role)
10. Parámetros en los include/import
11. Variables definidas en set_facts / variables definidas con register
12. Extra variables (--extra-vars [-e]): Siempre ganan.

Existen tres ámbitos donde una variable puede existir:

● Variables globales: pueden ser utilizadas en todo el playbook. Son


variables de configuración, variables de entorno y variables pasadas por la
línea de comandos.

© Alfaomega-RC Libros 49
ANSIBLE

● Variables del Play: son propias del Play que se está ejecutando, son
variables definidas con vars/vars_prompt/vars_files, variables y variables por
defecto de los roles.
● Variables del nodo: son variables asociadas directamente al nodo,
definidas en el inventario, include_vars, facts o variables definidas con register.

Roles
Con los roles podemos crear una estructura de ficheros y directorios para
separar los diferentes elementos: variables, tareas, handlers, ficheros y plantillas.
Esta estructura permite que sean reutilizados en diferentes proyectos.

La estructura de un playbook se muestra a continuación:


nombrerol/
├── defaults/
│ └── main.yml
├── files/
├── handlers/
│ └── main.yml
├── meta/
│ └── main.yml
├── tasks/
│ └── main.yml
├── templates/
└── vars/
└── main.yml

En la siguiente tabla se explica la funcionalidad de los subdirectorios del rol.

Subdirectorio Descripción
Contiene la lista principal de tareas a ser
tasks ejecutadas por un rol.
Contiene handlers, que pueden ser
utilizadas por este rol o incluso desde
handlers cualquier sitio fuera del rol.
defaults Variables por defecto para el rol.
vars Otras variables para el rol.
Contiene ficheros que pueden ser
files desplegados en los nodos usando este rol.

50 © Alfaomega-RC Libros
CAPÍTULO 4: PLAYBOOKS

Contiene plantillas que pueden ser


templates desplegadas usando este rol.
Define algunos datos meta para este rol,
meta normalmente roles necesarios para este.

Dentro de tasks/main.yml y handlers/main.yml podemos utilizar las


expresiones vistas import_tasks e include_tasks para separar las tareas en
diferentes ficheros. Es posible incluir la tarea include_vars y alojar el fichero de
variables dentro del directorio vars/.

Una vez definido uno o varios roles, debemos incluirlos dentro de nuestro
playbook. Para ello tenemos dos maneras de hacerlo:

● La manera clásica utilizando la sintaxis roles: y la lista de roles a incluir.


Podemos realizar tareas antes de incluir los roles utilizando pre_tasks: y tareas
después de incluir los roles utilizando post_tasks.
● Desde la versión 2.4 es posible usar las tareas import_role o include_role.

---
- name: Utilizar roles
hosts: servidor
pre_tasks:
- command: deshabilitar_monitorizacion
roles:
- mysql
- {name: httpd}
post_tasks:
- command: habilitar_monitorizacion
...

Un ejemplo de cómo podrían definirse nuestros roles se muestra a


continuación:

mysql/defaults/main.yml
---
mysql_port: 3306
...
mysql/tasks/main.yml
---
- name: Instalar la versión especificada

© Alfaomega-RC Libros 51
ANSIBLE

apt: name="mysql-server-{{ version }}" state=present


- name: Copiar fichero de configuración
template: src=my.cnf dest=/etc/mysql/my.cnf
notify: "Reiniciar MySQL"...
mysql/handlers/main.yml
---
- name: Reiniciar MySQL
service: name=mysqld state=restarted
...
mysql/templates/my.cnf (Plantilla a utilizar)
[client]
port= {{ mysql_port }}
socket= /var/run/mysqld/mysqld.sock
[mysqld_safe]
socket= /var/run/mysqld/mysqld.sock
nice= 0
[mysqld]
user= mysql
pid-file= /var/run/mysqld/mysqld.pid
socket= /var/run/mysqld/mysqld.sock
port= {{ mysql_port }}
basedir= /usr
datadir= /var/lib/mysql
tmpdir= /tmp
lc-messages-dir= /usr/share/mysql
skip-external-locking
bind-address= 0.0.0.0
key_buffer= 16M
max_allowed_packet= 16M
thread_stack= 192K
thread_cache_size = 8
myisam-recover = BACKUP
query_cache_limit= 1M
query_cache_size = 16M
log_error = /var/log/mysql/error.log
log_slow_queries= /var/log/mysql/mysql-slow.log
long_query_time = 1
expire_logs_days= 10
max_binlog_size = 100M
[mysqldump]
quick
quote-names
max_allowed_packet= 16M

52 © Alfaomega-RC Libros
CAPÍTULO 4: PLAYBOOKS

[mysql]
[isamchk]
key_buffer= 16M
!includedir /etc/mysql/conf.d/
httpd/vars/main.yml
paquete: "apache2-mpm-worker"
httpd/tasks/main.yml
---
- name: Instalar el paquete especificado
apt: name="{{ paquete }}" state=present
- name: Copiar fichero de configuración
template: src=ports.conf dest=/etc/apache2/ports.conf
notify: "Reiniciar Apache"...
httpd/handlers/main.yml
---
- name: Reiniciar Apache
service: name=apache2 state=restarted
...
httpd/files/ports.conf
Listen 80
<IfModule ssl_module>
Listen 443
</IfModule>
<IfModule mod_gnutls.c>
Listen 443
</IfModule>
httpd/meta/main.yml
---
dependencies:
- { role: comun, distro: "Debian" }

Si hay llamadas a tareas handlers se ejecutarán tres veces: después de las


tareas en pre_tasks, después de los roles y después de las tareas en post_tasks.

A partir de la versión 2.4 de Ansible, es posible realizar lo mismo con las tareas
import_role o include_role como se muestra a continuación.

---
- name: Utilizar roles
hosts: servidor

© Alfaomega-RC Libros 53
ANSIBLE

tasks:
- command: deshabilitar_monitorizacion
- import_role:
name: mysql
- include_role:
name: httpd
- command: habilitar_monitorizacion...

Cuando incluimos roles podemos pasarle variables o indicar condiciones si


queremos o no incluirlos.

Plantillas
Una plantilla (template) es un fichero dinámico que incluye variables e
instrucciones varias: condiciones, bucles, etc. Estas plantillas usan el lenguaje
Jinja2, que facilita el uso de plantillas y al igual que YAML es muy legible.

Algunas de las instrucciones que podemos utilizar se definen a continuación:

● Variables: {{ variable }} -> Por ejemplo {{ ansible_fqdn }}


● Control: {% instrucción %}

Tipo Sintaxis Ejemplo


Variables {{ variable }} {{ ansible_fqdn }}

Condición {% if condicion %} Condición:


{% endif %} {% if ansible_distribution == "Debian" %}
Este es un sistema Debian
{% if condicion %} {% else %}
{% elif %} Este no es un sistema Debian
{% else %} {% endif %}
{% endif %}

Bucle {% for var in lista %} Lista de usuarios:


{% endfor %} {% for usuario in lista_usuarios %}
{{ usuario }}
{% endfor %}

Comentario {# texto # {# Esto es un comentario #}

La tarea template procesa la plantilla en el servidor donde se está ejecutando


Ansible y el fichero procesado será transferido al nodo administrado.

54 © Alfaomega-RC Libros
CAPÍTULO 4: PLAYBOOKS

Un ejemplo de una plantilla para actualizar el fichero /etc/hosts de los


servidores con la lista de nodos del play (utilizando la variable play_hosts que
automáticamente se genera al ejecutar el playbook):

127.0.0.1 localhost localhost.localdomain localhost4


localhost4.localdomain4
::1 localhost localhost.localdomain localhost6
localhost6.localdomain6
{% for host in play_hosts %}
{{ hostvars[host]['ansible_default_ipv4']['address'] }} {{
hostvars[host]['ansible_hostname'] }} {{ host }}
{% endfor %}

Genera un fichero similar al siguiente:

127.0.0.1 localhost localhost.localdomain localhost4


localhost4.localdomain4
::1 localhost localhost.localdomain localhost6
localhost6.localdomain6
37.139.7.43 www www.oforte.net
91.121.79.141 cloud cloud.oforte.net
91.121.173.38 lab lab.oforte.net

Condiciones
Es posible condicionar la ejecución de una tarea, la inclusión de un fichero (ya
sea de tareas o de playbooks) o el uso de un rol, utilizando la expresión when.

En el siguiente ejemplo, la siguiente tarea se ejecutará solo si la distribución


del nodo que administramos es de tipo "Debian":

- name: Instalar apache2


apt: name=apache2 state=present
when: ansible_distribution == "Debian"

En el caso de que la condición no se cumpla, la tarea se mostrará como


"skipping".

TASK [Instalar apache2] ******************


skipping: [localhost]

© Alfaomega-RC Libros 55
ANSIBLE

La sintaxis es similar cuando incluimos un fichero, ya que es una tarea, en el


siguiente ejemplo incluimos un fichero dependiendo de la distribución.

- name: Instalar apache2


include_tasks: instalar_apache2.yml
when: ansible_distribution == "Debian"
- name: Instalar httpd
import_tasks: instalar_httpd.yml
when: ansible_distribution == "CentOS"

En el caso de roles, tenemos varias sintaxis posibles dependiendo del formato


que utilicemos para hacer referencia a ellos.

Modo clásico
roles:
- { name: apache2, http_port: 80, when: ansible_distribution == "Debian"}
- { name: httpd, http_port: 80, when: ansible_distribution == "CentOS" }

Nuevo modo (Ansible 2.4 o posterior)


tasks:
- include_role:
name: httpd
vars:
http_port: 80
when: ansible_distribution == "CentOS"
- include_role:
name: apache2
vars:
http_port: 80
when: ansible_distribution == "Debian"

En la expresión de las condiciones podemos combinar varias comprobaciones,


de tipo "y" (and) o de tipo "o" (or), en el siguiente ejemplo se incluye el rol
"apache2" si la distribución es Debian o Ubuntu.

- include_role:
name: apache2
vars:
http_port: 80
when: ansible_distribution == "Debian" or ansible_distribution == "Ubuntu"

56 © Alfaomega-RC Libros
CAPÍTULO 4: PLAYBOOKS

Las expresiones se pueden combinar como se muestra a continuación, en este


caso se comprueba primero que la variable acción sea instalar y se comprueba la
distribución.

when: accion == "instalar" and (ansible_distribution ==


"Debian" or ansible_distribution == "Ubuntu")

Las distintas condiciones que podemos realizar son las siguientes:

Expresión Descripción Ejemplo


elemento1 Comprueba si accion == "instalar"
== los dos
elemento2 elementos son
iguales.
elemento1 Comprueba si ansible_distribution != "Debian"
!= los dos
elemento2 elementos son
distintos
elemento1 Comprueba si ansible_distribution_major_version > 7
> elemento1 es
elemento2 mayor que
elemento2
elemento1 Comprueba si ansible_distribution_major_version >= 7
>= element1 es
elemento2 mayor o igual
que elemento2
elemento1 Comprueba si ansible_distribution_major_version < 8
< elemento1 es
elemento2 menor que
elemento2
elemento1 Comprueba si ansible_distribution_major_version <= 7
<= element1 es
elemento2 menor o igual
que elemento2

Otras condiciones lógicas se muestran en la siguiente tabla:

Expresión Descripción Ejemplo


elem1 ~ elem2 Comprueba si el valor '"x86" ~ ansible_architecture'
de elem1 está en el
valor de elem2

© Alfaomega-RC Libros 57
ANSIBLE

elemento1 in lista Comprueba si accion in ["inst","actu"]


elemento1 está en la
lista

elem1 not in lista Comprueba si elem1 no accion not in ["inst","actu"]


está en la lista

elem1 is defined Comprueba si la ac is defined and ac == "inst"


variable elem1 está
definida

elem is not defined Comprueba si la - fail: msg="La variable accion


variable elem no está debe ser definida"
definida. when: accion is not defined

Bucles
En el capítulo de plantillas hemos visto cómo podemos recorrer una lista y
utilizar los valores dentro de ella. En esta sección veremos cómo recorrer listas y
diccionarios para realizar tareas con los elementos.

WITH_ITEMS
Con la expresión with_items podemos recorrer los elementos de una lista . Por
ejemplo si queremos instalar una lista de paquetes, en vez de definir varias tareas
por cada uno de los elementos, utilizaremos la siguiente sintaxis:

- name: Instalar lista de paquetes requeridos


apt: name="{{ item }}" state=present
with_items:
- php5
- mariadb-server
- phpmyadmin

Como observamos en el ejemplo anterior, cuando utilizamos with_items la


variable por cada uno de los elementos es "{{ item }}". La salida de la tarea
anterior se muestra a continuación:

TASK [Instalar lista de paquetes requeridos] ***********


changed: [localhost] => (item=[u'php5', u'mariadb-server',
u'phpmyadmin'])

En caso de tener una lista de diccionarios, podemos utilizar los valores de cada
uno de los registros usando "{{ item.clave }}", como se muestra en el ejemplo

58 © Alfaomega-RC Libros
CAPÍTULO 4: PLAYBOOKS

siguiente donde definimos el nombre de software y el estado (absent para ser


eliminado o present para ser instalado):

- hosts: servidor
tasks:
- name: Instalar lista de paquetes requeridos
apt: name="{{ item.nombre}}" state="{{ item.estado }}"
with_items:
- {nombre: nginx, estado: absent}
- {nombre: apache2, estado: present}
- {nombre: php5, estado: present}
- {nombre: mariadb-server, estado: present}
- {nombre: phpmyadmin, estado: present}
TASK [Instalar lista de paquetes requeridos] ***********
ok: [servidor] => (item={u'nombre': u'nginx', u'estado': u'absent'})
ok: [servidor] => (item={u'nombre': u'apache2', u'estado': u'present'})
ok: [servidor] => (item={u'nombre': u'php5', u'estado': u'present'})
changed: [servidor] => (item={u'nombre': u'mariadb-server', u'estado':
u'present'})
ok: [servidor] => (item={u'nombre': u'phpmyadmin', u'estado': u'present'})

Con with_items podemos usar una variable que contenga la lista o el


diccionario.

- hosts: servidor
vars:
paquetes:
- php5
- mariadb-server
- phpmyadmin
tasks:
- name: Instalar lista de paquetes requeridos
apt: name="{{ item }}" state=present
with_items: "{{ paquetes }}"

Cuando se utiliza con condiciones, usando when, la condición se comprobará


por cada uno de los elementos. En el siguiente ejemplo distinguimos el paquete a
instalar (httpd o apache2) dependiendo de la distribución del nodo administrado:

- hosts: servidordebian
tasks:
- name: Instalar lista de paquetes requeridos

© Alfaomega-RC Libros 59
ANSIBLE

package: name="{{ item.nombre }}" state=present


when: ansible_distribution in item.distro
with_items:
- {nombre: httpd, distro: ["CentOS", "RedHat"]}
- {nombre: apache2, distro: ["Debian", "Ubuntu"]}
TASK [Instalar lista de paquetes requeridos] ************
skipping: [servidordebian] => (item={u'nombre': u'httpd',
u'distro': [u'CentOS', u'RedHat']})
ok: [servidordebian] => (item={u'nombre': u'apache2',
u'distro': [u'Debian', u'Ubuntu']})

WITH_NESTED

Es posible anidar dos listas generando una mezcla de los elementos. Veamos
un ejemplo:

usuarios agonzalez jveipen mperez


grupos administradores usuarios

Con with_nested se combinará cada usuario con cada uno de los grupos, en la
siguiente tabla se muestra cada combinación con la que será llamada la tarea.

Usuario Grupo
Agonzalez administradores
agonzalez Usuarios
jveipen administradores
jveipen usuarios
mperez administradores
mperez usuarios

El playbook para crear los usuarios basado en esos grupos (los grupos fueron
creados previamente):

- hosts: servidor
vars:
usuarios:
- agonzalez
- jveipen
- mperez

60 © Alfaomega-RC Libros
CAPÍTULO 4: PLAYBOOKS

grupos:
- administradores
- usuarios
tasks:
- group: name="{{ item }}"
with_items: "{{ grupos }}"
- user:
name: "{{ item[0] }}"
groups: "{{ item[1] }}"
append: true
with_nested:
- "{{ usuarios }}"
- "{{ grupos }}"
PLAY [servidor] **********
TASK [Gathering Facts] ****
ok: [ servidor]

TASK [group] **************


changed: [servidor] => (item=administradores)
changed: [servidor] => (item=usuarios)

TASK [user] ***************


changed: [servidor] => (item=[u'agonzalez', u'administradores'])
changed: [servidor] => (item=[u'agonzalez', u'usuarios'])
changed: [servidor] => (item=[u'jveipen', u'administradores'])
changed: [servidor] => (item=[u'jveipen', u'usuarios'])
changed: [servidor] => (item=[u'mperez', u'administradores'])
changed: [servidor] => (item=[u'mperez', u'usuarios'])

PLAY RECAP ****************


servidor : ok=3 changed=2 unreachable=0 failed=0
Comprobación.
# members administradores
agonzalez jveipen mperez
# members usuarios
agonzalez jveipen mperez

WITH_DICT

Con with_items observábamos cómo recorrer una lista, esta puede contener
un diccionario y acceder a los elementos del mismo. Con la expresión with_dict
podemos recorrer un diccionario que contiene varios elementos. La clave de cada
uno de los registros se referencia con "{{ item.key }}" y los valores

© Alfaomega-RC Libros 61
ANSIBLE

con "{{ item.value.elemento }}", en el siguiente ejemplo se crean los usuarios si


no existen, se asignan los grupos y se especifica la descripción:

- hosts: servidor
vars:
usuarios:
agonzalez:
grupos: "administradores, usuarios"
info: "CTO"
jveipen:
grupos: "administradores, usuarios"
info: "CEO"
mperez:
grupos: "usuarios"
info: "CFO"
tasks:
- user:
name: "{{ item.key }}"
groups: "{{ item.value.grupos }}"
comment: "{{ item.value.info }}"
with_dict: "{{ usuarios }}"
PLAY [servidor] **********
TASK [Gathering Facts] ****
ok: [servidor]
TASK [user] ***************
changed: [servidor] => (item={'value': {u'grupos':
u'administradores, usuarios', u'info': u'CEO'}, 'key':
u'jveipen'})
changed: [servidor] => (item={'value': {u'grupos':
u'administradores, usuarios', u'info': u'CTO'}, 'key':
u'agonzalez'})
changed: [servidor] => (item={'value': {u'grupos':
u'usuarios', u'info': u'CFO'}, 'key': u'mperez'})

PLAY RECAP ****************


servidor : ok=3 changed=2 unreachable=0 failed=0
Comprobación.
# finger agonzalez
Login: agonzalez Name: CTO
[...]
# groups agonzalez
agonzalez : agonzalez administradores usuarios

62 © Alfaomega-RC Libros
CAPÍTULO 4: PLAYBOOKS

En el capítulo de avanzado veremos cómo recorrer elementos de forma


avanzada.

Register
La expresión register permite guardar en una variable el resultado de una
acción realizada por una tarea. En el siguiente ejemplo, ejecutamos un comando
en el nodo administrado y alojamos el resultado en una variable.

- name: Mostrar uptime


hosts: servidor
tasks:
- command: uptime
register: salida_uptime
- debug: var=salida_uptime
PLAY [Mostrar uptime] *****
TASK [command] ************
changed: [servidor]
TASK [debug] **************
ok: [servidor] => {
"salida_uptime": {
"changed": true,
"cmd": [
"uptime"
],
"delta": "0:00:00.009831",
"end": "2018-03-04 20:39:55.061644",
"failed": false,
"rc": 0,
"start": "2018-03-04 20:39:55.051813",
"stderr": "",
"stderr_lines": [],
"stdout": " 20:39:55 up 4:27, 1 user, load average: 0.18,
0.05, 0.01",
"stdout_lines": [
" 20:39:55 up 4:27, 1 user, load average: 0.18, 0.05,
0.01"
]
}
}

PLAY RECAP ****************


servidor: ok=3 changed=1 unreachable=0 failed=0

© Alfaomega-RC Libros 63
ANSIBLE

Al ejecutar un comando obtenemos la siguiente información en la variable:

Clave Descripción
changed true/false -> Indica si la tarea ha
finalizado correctamente (rc=0)
failed true/false -> Indica si la tarea ha fallado.
skipped true/false -> Indica si la tarea ha sido
omitida por una condición.
rc El código devuelto por el comando (return
code), si es 0 el comando se ha ejecutado
correctamente.
start La fecha y hora de inicio de ejecución de la
tarea.
end La fecha y hora de la finalización de
ejecución de la tarea.
delta La duración de ejecución de la tarea.
stderr Si la tarea muestra un mensaje por la salida
de errores, se alojará en este apartado.
stderr_lines Igual que stderr, pero como una lista: cada
línea será un elemento de ella.
stdout La salida devuelta por la tarea.
stdout_lines Igual que stdout, pero como una lista: cada
línea será un elemento de ella.

Si queremos mostrar solo la salida estándar:

- debug: msg="{{ salida_uptime.stdout }}"

delegate_to

En ciertas situaciones es útil ejecutar comandos en el nodo control, es decir,


donde estamos ejecutando el Playbook. Por ejemplo si deseamos realizar una
llamada a una página web o a una API, no necesitamos realizarla desde el nodo
administrado. Además, delegate_to permite también delegar una tarea a un
servidor distinto, incluso aunque no esté en el inventario. Ejemplo:

64 © Alfaomega-RC Libros
CAPÍTULO 4: PLAYBOOKS

Contenido del playbook


- name: Uso de delegate_to
hosts: www.oforte.net
tasks:
- name: Tarea ejecutada en el nodo remoto
command: uname -n
- name: Tarea ejecutada en otro nodo
command: uname -n
delegate_to: cloud.oforte.net
Resultado mostrado (con -v).
PLAY [Uso de delegate_to]

TASK [Gathering Facts]


ok: [www.oforte.net]

TASK [Tarea ejecutada en el nodo remoto]


changed: [www.oforte.net] => {"changed": true, "cmd":
["uname", "-n"], "delta": "0:00:00.002237", "end": "2018-
04-25 20:27:23.039613", "rc": 0, "start": "2018-04-25
20:27:23.037376", "stderr": "", "stderr_lines": [],
"stdout": "www", "stdout_lines": ["www"]}

TASK [Tarea ejecutada en otro nodo]


changed: [www.oforte.net -> cloud.oforte.net] =>
{"changed": true, "cmd": ["uname", "-n"], "delta":
"0:00:00.024211", "end": "2018-04-25 20:27:23.327394",
"rc": 0, "start": "2018-04-25 20:27:23.303183", "stderr":
"", "stderr_lines": [], "stdout": "cloud.oforte.net",
"stdout_lines": ["cloud.oforte.net"]}

PLAY RECAP
www.oforte.net : ok=3 changed=2
unreachable=0 failed=0

ignore_errors
Si una tarea devuelve un error, ya sea ejecutar un comando o utilizar un
módulo de Ansible, el resto de tareas para ese nodo no se ejecutarán. Ansible
permite ignorar un error si consideramos que no afectará al resto de tareas, para
ello utilizaremos la expresión ignore_errors.

© Alfaomega-RC Libros 65
ANSIBLE

- name: ignorar errores


hosts: servidor
tasks:
- command: cat /etc/hosts2
register: salida_cat
ignore_errors: True
- debug: msg="{{ salida_cat.stderr }}"
PLAY [ignorar errores] ****
TASK [Gathering Facts] ****
ok: [servidor]
TASK [command] ************
fatal: [servidor]: FAILED! => {"changed": true, "cmd":
["cat", "/etc/hosts2"], "delta": "0:00:00.009284", "end":
"2018-03-05 22:17:34.275783", "failed": true, "msg": "non-
zero return code", "rc": 1, "start": "2018-03-05
22:17:34.266499", "stderr": "cat: /etc/hosts2: No such file
or directory", "stderr_lines": ["cat: /etc/hosts2: No such
file or directory"], "stdout": "", "stdout_lines": []}
...ignoring
TASK [debug] **************
ok: [localhost] => { "msg": "cat: /etc/hosts2: No such
file or directory"}

PLAY RECAP ****************


servidor : ok=3 changed=1 unreachable=0 failed=0

Podemos comprobar si una tarea ha fallado con la sintaxis: "variable|failed",


en el siguiente ejemplo mostramos la salida estándar si la tarea anterior que
registra la variable ha sido correcto o mostramos la salida de error en caso de
problema.

- name: ignorar errores


hosts: servidor
tasks:
- command: cat {{ fichero }}
register: salida_cat
ignore_errors: True
- debug:
msg: "Contenido fichero: {{ salida_cat.stdout }}"
when: not salida_cat|failed
- debug:
msg: "Error commando: {{ salida_cat.stderr }}"
when: salida_cat|failed

66 © Alfaomega-RC Libros
CAPÍTULO 4: PLAYBOOKS

# ansible-playbook -e fichero=/etc/timezone ignore.yml


PLAY [ignorar errores] ****TASK [Gathering Facts] ****
ok: [servidor]
TASK [command] ************
changed: [servidor]
TASK [debug] **************
ok: [servidor] => {
"msg": "Contenido fichero: Europe/Paris"
}
TASK [debug] **************
skipping: [servidor]

PLAY RECAP ****************


servidor: ok=3 changed=1 unreachable=0 failed=0
# ansible-playbook -e fichero=/etc/noexiste ignore.yml
PLAY [ignorar errores] ****
TASK [Gathering Facts] ****
ok: [servidor]
TASK [command] ************
fatal: [servidor]: FAILED! => {"changed": true, "cmd":
["cat", "/etc/noexiste"], "delta": "0:00:00.009028", "end":
"2018-03-05 22:25:28.471128", "failed": true, "msg": "non-
zero return code", "rc": 1, "start": "2018-03-05
22:25:28.462100", "stderr": "cat: /etc/noexiste: No such
file or directory", "stderr_lines": ["cat: /etc/noexiste:
No such file or directory"], "stdout": "", "stdout_lines":
[]}
...ignoring
TASK [debug] **************
skipping: [servidor]
TASK [debug] **************
ok: [servidor] => {
"msg": "Error commando: cat: /etc/noexiste: No such file
or directory"
}
PLAY RECAP ****************
servidor: ok=3 changed=1 unreachable=0 failed=0

Es posible especificar ignore_errors a nivel de Play, pero es totalmente no


recomendable debido a que se pueden ignorar errores importantes en las tareas y
debería utilizarse otra estrategia para omitir errores.

© Alfaomega-RC Libros 67
ANSIBLE

failed_when y changed_when
Ansible nos permite especificar condiciones para marcar una tarea como
fallida o como que ha modificado algo. Un ejemplo es ejecutando un comando, la
tarea es marcada como cambiada cuando el código de salida (rc) es igual a 0 y
fallida si es distinta a cero. Pero normalmente solo queremos marcar la tarea
como que ha cambiado algo si el texto de salida estándar indica que se ha
modificado. Lo mismo para marcar una tarea como fallida, desearemos
comprobar el texto de salida para saber si ha fallado.

El siguiente playbook contiene una tarea que será marcada


como cambiada solo si el paquete se instala.
- name: install lftp
hosts: servidor
tasks:
- command: apt-get -y install lftp
register: salida_apt
changed_when: "'is already the newest version' not in
salida_apt.stdout"
El siguiente playbook contiene una tarea que será marcada
como fallida si el nombre DNS no resuelve.
- name: Comprobar dominio
hosts: servidor
tasks:
- command: dig +short ejemplo.oforte.net
register: salida_dig
failed_when: salida_dig.stdout == ""

Es posible establecer que una tarea nunca sea marcada como cambiada o
fallida utilizando como condición las palabras: False, false o el número 0.

- name: Esta tarea nunca falla


hosts: servidor
tasks:
- command: noexiste
changed_when: False
failed_when: False

68 © Alfaomega-RC Libros
CAPÍTULO 4: PLAYBOOKS

Bloques
Los bloques en Ansible nos permiten agrupar un conjunto de tareas afines. La
mayoría de acciones que se pueden aplicar a una tarea se pueden aplicar a un
bloque: condiciones, privilegios, etc. La sintaxis es la siguiente:

- name: Ejemplo de bloque


hosts: servidor
tasks:
- block:
- name: tarea1
tarea:
- name: tarea2
tarea:
when: condicion
become: True

En el siguiente ejemplo se ve la gran utilidad para agrupar tareas.

- name: Ejemplo de bloque


hosts: all
become: True
handlers:
- name: restart_apache2
service: name=apache2 state=restarted
- name: restart_httpd
service: name=httpd state=restarted
tasks:
- name: Instalar apache2 en sistemas Debian
block:
- name: Instalar apache2
apt:
name: apache2
state: latest
- name: Copiar configuración
copy:
src: templates/apache2.conf.j2
dest: /etc/apache2/apache2.conf
notify: restart_apache2
when: ansible_distribution == "Debian"
remote_user: alberto
- name: Instalar apache2 en sistemas Centos
block:

© Alfaomega-RC Libros 69
ANSIBLE

- name: Instalar httpd


yum:
name: httpd
state: latest
- name: Copiar configuración
copy:
src: templates/httpd.conf.j2
dest: /etc/httpd/conf.d/httpd.conf
notify: restart_httpd
when: ansible_distribution == "CentOS"
remote_user: centos

Los bloques nos permite también gestionar los errores que puedan surgir de
las tareas que contienen y realizar acciones preventivas. Por ejemplo, si copiamos
un fichero de configuración y al reiniciar el servicio falla, es posible ejecutar una
tarea para restaurar el estado anterior. La estructura es la siguiente:

- hosts: servidor
gather_facts: False
tasks:
- name: Gestionar errores
block:
- name: Tarea1
tarea:
rescue:
- name: Tarea a ejecutar si falla Tarea1
tarea:
always:
- name: Tarea que se ejecuta siempre
tarea:

En el siguiente ejemplo se muestra el uso de rescue y de always. En el bloque


se intenta ejecutar un comando (lsb_release) y en caso de no existir, se lee la
información desde los ficheros.

Contenido del playbook.


- hosts: all
tasks:
- name: Gestionar errores
block:
- name: Leer la configuración de lsb_release

70 © Alfaomega-RC Libros
CAPÍTULO 4: PLAYBOOKS

command: lsb_release -d
register: version
rescue:
- name: Si no existe lsb_release
command: cat /etc/debian_version
register: version
when: ansible_distribution == "Debian"
- name: Si no existe lsb_release
command: cat /etc/centos-release
register: version
when: ansible_distribution == "CentOS"
always:
- name: Ver versión
debug: msg="{{ version.stdout }}"
Salida de la ejecución.
PLAY [all] ****************
TASK [Gathering Facts] ****
ok: [debian01]
ok: [centos01]
TASK [Leer la configuración de lsb_release] ***************
changed: [debian01]
fatal: [centos01]: FAILED! => {"changed": false, "cmd":
"lsb_release -d", "msg": "[Errno 2] No such file or
directory", "rc": 2}
TASK [Si no existe lsb_release] ***********
skipping: [centos01]
TASK [Si no existe lsb_release] ***********
changed: [centos01]
TASK [Ver versión] ********
ok: [centos01] => {
"msg": "CentOS Linux release 7.4.1708 (Core) "
}
ok: [debian01] => {
"msg": "Description:\tDebian GNU/Linux 9.3 (stretch)"
}

PLAY RECAP ****************


centos01 : ok=3 changed=1 unreachable=0 failed=1
debian01 : ok=3 changed=1 unreachable=0 failed=0

© Alfaomega-RC Libros 71
MÓDULOS

MÓDULOS

Ansible está compuesto de una multitud de módulos, que son los encargados
de administrar sistemas, dispositivos, usuarios y una gran cantidad de diferentes
elementos. Cada tarea en un playbook está asociada a un módulo. Cada módulo
contiene varios argumentos que pueden ser obligatorios u opcionales, y además
suelen tener valores por defecto.

Los módulos se agrupan en las siguientes categorías:

Categoría Descripción
Cloud Módulos para administrar proveedores de cloud
(de la nube).
Módulos para gestionar diferentes tipos de
Clustering cluster.
Módulos para ejecutar comandos en nodos
Commands remotos.
Crypto Módulos para OpenSSL.
Módulos para gestionar diferentes gestores de
Database base de datos.
Files Módulos para manipular y tratar ficheros.
Módulos para administrar distintos
Identity proveedores de autenticación.
ANSIBLE

Inventory Módulos para tratar inventario de nodos.


Messaging Módulos para gestionar RabbitMQ.
Monitoring Módulos para gestionar y administrar
herramientas de monitorización.
Net Tools Módulos para herramientas de red.
Network Módulos para gestionar dispositivos de red.
Módulos para realizar distintos tipos de
Notification notificación.
Módulos para administrar software a través de
Packaging gestores de paquetes.
Remote Módulos para gestionar nodos de forma remota.
Management
Módulos para gestionar software de control de
Source Control versiones.
Módulos para administrar componentes de
Storage almacenamiento.
Módulos para gestionar diferentes elementos
System dentro de los sistemas.
Utilities Módulos con utilidades propias de Ansible.
Web Módulos para gestionar infraestructuras web.
Infrastructure
Windows Módulos para gestionar servidores Windows.

Es posible listar toda la lista de módulos para la versión actual utilizando el


comando ansible-doc con la opción -l.

# ansible-doc –l
a10_server Manage A10 Networks AX/SoftAX/Thunder/vThunder devices' server object.
a10_server_axapi3 Manage A10 Networks AX/SoftAX/Thunder/vThunder devices
a10_service_group Manage A10 Networks AX/SoftAX/Thunder/vThunder devices' service
groups.
a10_virtual_server Manage A10 Networks AX/SoftAX/Thunder/vThunder devices' virtual
servers.
accelerate Enable accelerated mode on remote node
aci_aep Manage attachable Access Entity Profile (AEP) on Cisco ACI fabrics
(infra:AttEntityP)
[...]

74 © Alfaomega-RC Libros
CAPÍTULO 5: MÓDULOS

Utilizando ansible-doc seguido del nombre de un módulo, obtendremos la


información sobre su función, la lista de argumentos (indicando si es obligatorio u
opcional), información del creador, diferente información de utilidad y una lista
de ejemplos variados. En la siguiente tabla describimos la información mostrada al
obtener información del módulo group.

Comando ansible-doc group


Descripción > GROUP (/usr/lib/python2.7/site-
del módulo packages/ansible/modules/system/group.py)
Manage presence of groups on a host. For
Windows targets, use the [win_group] module
instead.
Opciones (el OPTIONS (= is mandatory):
símbolo igual - gid
[=] indica Optional `GID' to set for the group.
que es [Default: (null)]
obligatorio). = name
Name of the group to manage.
- state
Whether the group should be present or not on
the remote host.
(Choices: present, absent)[Default: present]
- system
If `yes', indicates that the group created is a
system group.
(Choices: yes, no)[Default: no]

Información NOTES:
extra * For Windows targets, use the [win_group]
module instead.
Requisitos REQUIREMENTS: groupadd, groupdel, groupmod
Autor AUTHOR: Stephen Fromm (@sfromm)
METADATA:
status:
- stableinterface
supported_by: core
Ejemplos de EXAMPLES:
uso # Example group command from Ansible
Playbooks
- group:
name: somegroup
state: present

© Alfaomega-RC Libros 75
ANSIBLE

Módulos tratados de fichero


Estos módulos permiten trabajar con ficheros, plantilla y directorio. El listado
de los módulos disponibles es el siguiente:

Establece y obtiene información de listas de


acl control de acceso (ACLs).
Crea un fichero comprimido a partir de una lista
archive de ficheros o estructura de directorios.
Arma un fichero de configuración desde
assemble fragmentos.
Inserta/actualiza/elimina un bloque de texto de
blockinfile un fichero.
copy Copia ficheros a ubicaciones remotas.
Obtiene ficheros de un nodo remoto al servidor
fetch donde se ejecuta Ansible.
file Establece atributos a ficheros.
Devuelve una lista de ficheros a partir de un
find patrón dado.
ini_file Gestiona valores de un fichero con formato INI.
Asegura que una línea está en un fichero, o
lineinfile reemplaza una usando expresiones regulares.
Reemplaza las coincidencias de un texto
replace especificado por otro indicado.
Obtiene información de fichero o sistemas de
stat ficheros.
Módulo para sincronizar contenido utilizando
synchronize rsync.
template Procesa y copa una plantilla a un nodo remoto.
Extrae un fichero (opcionalmente después de
unarchive copiarlo al nodo).

Otros módulos dentro de esta categoría no detallados en este libro son:

iso_extract Extrae ficheros de una imagen ISO.


patch Aplica parches utilizando la herramienta patch.
tempfile Crea ficheros o directorios temporales.

76 © Alfaomega-RC Libros
CAPÍTULO 5: MÓDULOS

xattr Establece/obtiene atributos extendidos.


Administra partes de ficheros o cadenas con
xml formato XML.

ARGUMENTOS SELINUX

Estos argumentos se aplican a sistemas con RHEL o derivados para tratar


SELINUX.
selevel Nivel (Level) del contexto SELinux del fichero.
Valor por defecto: s0.
serole Rol del contexto SELinux del fichero. Por defecto el
definido en el sistema.
setype Tipo del contexto SELinux del fichero. Por defecto
el definido en el sistema.
seuser Usuario del contexto SELinux del fichero.

ARGUMENTOS PERMISOS

Estos argumentos gestionan los permisos de ficheros y directorios.

Argumentos Opciones Descripción


attributesattr Atributo que el fichero o directorio
debe tener.
backup no Indica si crear un fichero de copia
yes de seguridad incluyendo la fecha y
hora.
group Nombre del grupo que debe ser dueño
del fichero/directorio.
local_follow yes Indica si debe seguir un enlace
no simbólico.
mode Modo que el fichero o directorio debe
tener. Por ejemplo: 0644 o
u=rw,g=r,o=r/
owner Nombre del usuario que debe ser dueño
del fichero/directorio.
unsafe_writes yes Prevenir escrituras inseguras:
no prevenir corrupción de datos o
lectura de datos inconsistentes.

© Alfaomega-RC Libros 77
ANSIBLE

validate Comando a utilizar la validez del


contenido del fichero. La ruta del
fichero a validar es pasado a través
de la expresión '%s'.

MÓDULO ACL

Argumentos obligatorios
path=ruta La ruta completa del fichero u objeto.
Argumentos opcionales (Negrita indica el valor por defecto)
Argumentos Opciones Descripción
yes Si el destino es un directorio,
no estableciendo esta opción a yes, hará
este ACL como el defecto para el
default contenido creado dentro del mismo.
Usuario real o grupo al que se aplica
la ACL cuando se seleccionan tipos de
entidades coincidentes, usuario o
entity grupo.
user El tipo de entidad del ACL a aplicar.
group´
mask
etype other
yes Indica si debe seguir enlaces
follow no simbólicos si son encontrados.
Permisos a aplicar/eliminar que pueden
ser una combinación de r (lectura), w
permissions (escritura) y x (ejecución).
yes Establece de forma recursiva la ACL
recursive no indicada.
query Define si la ACL debe estar presente o
presen no. El estado query obtiene el valor
state tabsent actual sin cambiarlo.

En la siguiente tabla se muestran diferentes ejemplos y resultados.

Consultar los ACL de un fichero específico.


- name: Consultar ACLs
hosts: servidor

78 © Alfaomega-RC Libros
CAPÍTULO 5: MÓDULOS

gather_facts: False
tasks:
- acl:
path: /etc/apache2/sites-enabled/005-correo.conf
register: datos_acl
- debug: var=datos_acl
TASK [debug] **************
ok: [servidor] => {
"datos_acl": {
"acl": [
"user::rw-",
"group::r--",
"other::r--"
],
"changed": false,
"failed": false,
"msg": "current acl"
}
}
Añadir ACL para que un usuario pueda modificar el fichero.
- name: Modificar y Consultar ACLs
hosts: servidor
gather_facts: False
tasks:
- acl:
path: /etc/apache2/sites-enabled/005-correo.conf
entity: alberto
etype: user
permissions: rw
state: present
- acl:
path: /etc/apache2/sites-enabled/005-correo.conf
register: datos_acl
- debug: var=datos_acl
TASK [debug] **************
ok: [servidor] => {
"datos_acl": {
"acl": [
"user::rw-",
"user:alberto:rw-",
"group::r--",
"mask::rw-",
"other::r--"

© Alfaomega-RC Libros 79
ANSIBLE

],
"changed": false,
"failed": false,
"msg": "current acl"
}
}

# getfacl /etc/apache2/sites-enabled/005-correo.conf
# file: etc/apache2/sites-enabled/005-correo.conf
# owner: root
# group: root
user::rw-
user:alberto:rw-
group::r--
mask::rw-

MÓDULO ARCHIVE

Argumentos obligatorios
path=ruta Ruta absoluta remota, expresión o lista de
rutas o de expresiones de ficheros(o) a
comprimir o archivar.
Argumentos permisos y Argumentos SELinux
Argumentos opcionales (Negrita indica el valor por defecto)
Argumentos Opciones Descripción
dest El nombre del fichero del archivo
destino. Requerido cuando se
especifican múltiples ficheros.
exclude_path Ruta absoluta remota, expresión o
listas de rutas o de expresiones de
fichero(s) a excluir del archivo.
format gzbz2 El tipo de compresión a utilizar.
zip
remove Elimina cualquier fichero origen y
directorio después de archivarlo.

80 © Alfaomega-RC Libros
CAPÍTULO 5: MÓDULOS

Playbook para archivar el directorio /etc/ en un fichero


con la fecha (i.e. /var/backups/etc-2018-03-09.tgz)
- name: Backup del directorio /etc/ incluyendo la fecha
hosts: servidor
tasks:
- archive:
path: /etc/
dest: "/var/backups/etc-{{ ansible_date_time.date }}.tgz"

MÓDULO ASSEMBLE

Argumentos obligatorios
src=ruta Un directorio existente que contiene los
ficheros origen.
dest=ruta El fichero a crear usando la concatenación de
todos los ficheros origen.
Argumentos permisos y Argumentos SELinux
Argumentos opcionales (Negrita indica el valor por defecto)
Argumentos Opciones Descripción

decrypt yes Esta opción controla si los ficheros


no deben ser descifrados automáticamente
(ficheros cifrados con Ansible
Vault).
delimiter Un delimitador para separar el
contenido de los ficheros.
ignore_hidden Indica si los ficheros que empiezan
por '.' deben ser ignorados o no.
regexp Ensambla ficheros solo si esta
expresión regular se cumple.
remote_src True Si este argumento es False, se
False buscarán los ficheros en el nodo que
se ejecuta Ansible en vez de en el
nodo administrado.

En el siguiente ejemplo tenemos un directorio con ficheros por cada entorno,


relacionando IP con el nombre DNS para generar el fichero /etc/hosts

© Alfaomega-RC Libros 81
ANSIBLE

Contenido de los ficheros dentro de /root/servidores.


# cat /root/servidores/_localhost
127.0.0.1 localhost.localdomain localhost
::1 localhost localhost.localdomain localhost6
localhost6.localdomain6
# cat /root/servidores/dev
10.0.20.1 dev21.oforte.net
10.0.20.2 dev22.oforte.net
10.0.20.3 dev23.oforte.net
# cat /root/servidores/qa
10.0.10.1 qa10.oforte.net
10.0.10.2 qa11.oforte.net
10.0.10.3 qa12.oforte.net
# cat /root/servidores/prod
10.0.0.1 prod01.oforte.net
10.0.0.2 prod02.oforte.net
10.0.0.3 prod03.oforte.net
Playbook to "ensamblar" los ficheros.
- name: Unir ficheros de configuración
hosts: servidor
tasks:
- assemble:
src: /root/servidores
dest: /etc/hosts
delimiter: "### INICIO FICHERO ###"
Contenido del fichero /etc/hosts después de ejecutarlo.
127.0.0.1 localhost.localdomain localhost
::1 localhost localhost.localdomain localhost6
localhost6.localdomain6
### INICIO FICHERO ###
10.0.20.1 dev21.oforte.net
10.0.20.2 dev22.oforte.net
10.0.20.3 dev23.oforte.net
### INICIO FICHERO ###
10.0.0.1 prod01.oforte.net
10.0.0.2 prod02.oforte.net
10.0.0.3 prod03.oforte.net
### INICIO FICHERO ###
10.0.10.1 qa10.oforte.net
10.0.10.2 qa11.oforte.net
10.0.10.3 qa12.oforte.net

82 © Alfaomega-RC Libros
CAPÍTULO 5: MÓDULOS

MÓDULO BLOCKINFILE

Argumentos obligatorios
path=ruta El fichero a modificar.
dest=ruta
destfile=ruta
name=ruta
Argumentos permisos y Argumentos SELinux
Argumentos opcionales (Negrita indica el valor por defecto)
Argumentos Opciones Descripción
blockcontent El texto a insertar en medio de las
marcas.
create no Crea un fichero nuevo si no existe.
yes
follow no Indica si seguir un enlace
yes simbólico.
insertafter EOF Si se especifica, se insertará
*regex* después de la línea encontrada con
dicha expresión. Si no se
especifica, se insertará al final
del fichero.
insertbefore BOF Si se especifica, se insertará antes
*regex* de la línea encontrada con dicha
expresión. Si no se especifica, se
insertará al final del fichero.
marker La línea a utilizar como marca.
"{mark}" será sustituido con "BEGIN"
o "END".
state present Indica si el bloque debe estar
absent presente o no.

En el siguiente ejemplo incluimos un bloque de textos dentro del fichero


/etc/motd:
Contenido del playbook.
- name: Definir el texto a mostrar en el fichero motd
hosts: servidor
tasks:
- blockinfile:
path: /etc/motd

© Alfaomega-RC Libros 83
ANSIBLE

backup: yes
block: |
Este es un sistema protegido,
solo está permitido el acceso a usuarios autorizados
Contenido del fichero /etc/motd después de la ejecución.
# cat /etc/motd
Linux cloud.oforte.net 3.16.0-4-amd64 #1 SMP Debian
server : 211983
ip : 91.121.79.141
hostname : cloud.oforte.net
# BEGIN ANSIBLE MANAGED BLOCK
Este es un sistema protegido,
solo está permitido el acceso a usuarios autorizados
# END ANSIBLE MANAGED BLOCK

MÓDULO COPY

Argumentos obligatorios
Ruta absoluta donde el fichero será copiado.
dest=ruta Si el destino no existe, será creado.
Argumentos permisos y Argumentos SELinux
Argumentos opcionales (Negrita indica el valor por defecto)
Argumentos Opciones Descripción
content Si no se utiliza el argumento src,
el contenido indicado en este
argumento será usado para rellenar
el fichero.
decrypt yes Controla si se descifra
no automáticamente el fichero (cifrado
con Ansible Vault).
directory_mode Cuando se realiza una copia
recursiva indica si se establecen
los permisos de los directorios.
follow no Indica si debe ser un enlace
yes simbólico.
forcethirsty yes Si se debe sobrescribir el contenido
no del fichero. Si se establece a no,
solo se copiará si el destino no
existe.

84 © Alfaomega-RC Libros
CAPÍTULO 5: MÓDULOS

remote_src no Por defecto copia un


yes fichero/directorio desde el nodo que
se ejecuta Ansible. En caso de
habilitar este argumento se copiará
un fichero internamente en el nodo
administrado.
src Ruta del fichero a copiar al nodo
remoto. Puede ser ruta absoluta o
relativa.

En el siguiente ejemplo copiamos un fichero que contiene las reglas sudo y


comprobamos que la sintaxis sea correcta. El dueño del fichero es el usuario root
y el grupo root, el permiso del fichero será 440 (fichero de solo lectura para
usuario y grupo).

Contenido del playbook.


- name: Copiar fichero sudoers
hosts: servidor
tasks:
- copy:
src: ficheros/sudoers
dest: /etc/sudoers
owner: root
group: root
mode: u=r,g=r,o=
validate: /usr/sbin/visudo -cf %s
En caso de que el fichero no contenga una sintaxis correcta
(detectado por el comando definido en validate) la tarea
fallará y el fichero no será copiado.
PLAY [Copiar fichero sudoers] *************
TASK [Gathering Facts] ****
ok: [servidor]
TASK [copy] **************
fatal: [localhost]: FAILED! => {"changed": false,
"checksum": "7b28007f904781aed94356dcbcc2aec1620ceaf5",
"exit_status": 1, "failed": true, "msg": "failed to
validate", "stderr": ">>> /root/.ansible/tmp/ansible-tmp-
1520685794.99-64785980936861/source: syntax error near line
12 <<<\n", "stderr_lines": [">>>
/root/.ansible/tmp/ansible-tmp-1520685794.99-
64785980936861/source: syntax error near line 12 <<<"],
"stdout": "parse error in /root/.ansible/tmp/ansible-tmp-

© Alfaomega-RC Libros 85
ANSIBLE

1520685794.99-64785980936861/source near line 12\n",


"stdout_lines": ["parse error in
/root/.ansible/tmp/ansible-tmp-1520685794.99-
64785980936861/source near line 12"]}
to retry, use: --limit @/tmp/sudo.retry
PLAY RECAP ***************
localhost : ok=1 changed=0 unreachable=0 failed=1

MÓDULO FETCH

Argumentos obligatorios
src=ruta El fichero en el nodo remoto a obtener.
El directorio donde salvar el fichero
obtenido. Se creará un subdirectorio con
dest=ruta el nombre del nodo.
Argumentos opcionales (Negrita indica el valor por defecto)
fail_on_missing yes Indica si la tarea será marcada como
no fallida si el fichero remoto que
deseamos obtener no existe.
flat Permite sobrescribir el
comportamiento por defecto de crear
un subdirectorio con el nombre del
nodo.
validate_checksum yes Verifica si el fichero origen y el
validate_m5 no destino coinciden a través de
comprobaciones checksum.

El siguiente playbook copia de los servidores el fichero de configuración de red


/etc/network/interfaces al servidor donde ejecutamos el playbook.

Contenido del playbook usando el módulo fetch.

- name: Copiar desde los servidores el fichero /etc/network/interfaces


hosts: all
tasks:
- fetch:
src: /etc/network/interfaces
dest: /backup/network-config/

86 © Alfaomega-RC Libros
CAPÍTULO 5: MÓDULOS

El directorio, si no existe, será creado y esta es la


estructura. (En caso de no definir flat=yes)
# tree /backup/network-config/
/backup/network-config/
├── cloud.oforte.net
│ └── etc
│ └── network
│ └── interfaces
├── lab.oforte.net
│ └── etc
│ └── network
│ └── interfaces
└── www.oforte.net
└── etc
└── network
└── interfaces
9 directories, 3 files

En el caso de querer copiar los ficheros pero sin tener la estructura


anteriormente mostrada, activaremos la opción flat.
Contenido del playbook.
- name: Copiar desde los servidores el fichero /etc/network/interfaces
hosts: all
tasks:
- fetch:
src: /etc/network/interfaces
dest: /backup/network-config-flat/interfaces-{{inventory_hostname}}
flat: yes

Contenido del directorio destino.


# tree /backup/network-config-flat/
/backup/network-config-flat/
├── interfaces-cloud.oforte.net
├── interfaces-lab.oforte.net
└── interfaces-www.oforte.net
0 directories, 3 files

MÓDULO FILE
Argumento obligatorio
path=ruta Ruta del fichero a ser administrado.
dest=ruta
name=ruta

© Alfaomega-RC Libros 87
ANSIBLE

Argumentos permisos y Argumentos SELinux


Argumentos opcionales (Negrita indica el valor por defecto)
follow no Indica si seguir enlaces simbólicos.
yes
force no Fuerza la creación de enlaces simbólicos
yes en dos casos: el fichero origen no
existe o el fichero destino existe y es
un fichero.
recurse no Establece de forma recursiva los
yes atributos (solo aplicable a
state=directory).
src Ruta del fichero a enlazar (solo
aplicable a state=link).
state file Si directory es especificado, todos los
link subdirectorios serán creados si no
directory existen. Con file, el fichero NO será
hard creado si no existe. Con link será
touch creado o cambiado. Si se ha especificado
absent absent y es un directorio, se borrará de
forma recursiva. Con touch un fichero
vacío se creará si no existe.

Ejemplos:

Cambiar/asegurar los permisos de un fichero.


- name: Establecer permisos al fichero authorized_keys
hosts: servidor
tasks:
- file:
path: ~/.ssh/authorized_keys
mode: 0600
owner: root
group: root
Crear un enlace simbólico desde /etc/issue a
/etc/issue.net.
- name: Enlazar /etc/issue a /etc/issue.net
hosts: servidor
tasks:
- name: Eliminar /etc/issue.net antes de crear el enlace
file:

88 © Alfaomega-RC Libros
CAPÍTULO 5: MÓDULOS

path: /etc/issue.net
state: absent
- name: Crear el enlace simbólico
file:
src: /etc/issue
path: /etc/issue.net
state: link
En el siguiente ejemplo creamos un directorio llamado
/var/log/journal para que journald sea persistente.
- name: Crear el directorio /var/log/journal
hosts: servidor
tasks:
- name: Crear /var/log/journal si no existe
file:
path: /var/log/journal
state: directory
owner: root
group: systemd-journal
mode: 2755
notify: restart_journald
handlers:
- name: restart_journald
service:
name: systemd-journald
state: restarted

Crea un fichero si no existe o actualiza la fecha de


modificación/acceso/cambio.
- name: Crear un fichero vacío si no existe
hosts: servidor
tasks:
- file:
path: /tmp/instalando_programa
state: touch

MÓDULO FIND

Argumentos obligatorios
paths=ruta(s) Lista de ruta de directorios a buscar. Todas
name=ruta(s) las rutas deben ser absolutas.
path=ruta(s)

© Alfaomega-RC Libros 89
ANSIBLE

Argumentos opcionales (Negrita indica el valor por defecto)


age Selecciona ficheros que su
antigüedad es igual o mayor al
tiempo especificado. Si se utiliza
un número negativo, buscará
ficheros igual o menor al tiempo
especificado.Se pueden especificar
segundos, minutos, horas, días o
semanas especificando la primera
letra de esas palabras en inglés,
por ejemplo: 1d.

age_stamp mtime Elige la propiedad del fichero a


atime utilizar para la comparación.
ctime
contains Una o más expresiones regulares a
buscar dentro del contenido de los
ficheros.
file_type file Tipo de fichero a seleccionar.
any
directory
link
follow no Indica si seguir a un enlace
yes simbólico.
get_checksum no Indica si obtener el checksum en
yes formato sha1.
hidden no Indica si deben incluirse ficheros
yes ocultos o deben ser ignorados.
patternspattern Una o más expresiones, controlado
por la opción use_regex.
recurse no
Si el destino es un directorio,
yes
indica si de forma recursiva se
recorre el directorio.
size Encuentra ficheros cuyo tamaño sea
igual o mayor que el especificado.
Con número negativo se encuentran
con tamaño igual o menor que el
valor indicado. Se pueden
especificar las letras: b, k, m,
g, y t.

90 © Alfaomega-RC Libros
CAPÍTULO 5: MÓDULOS

use_regex no Si es falso, se utilizan


yes expresiones básicas, si es verdad
expresiones regulares de Python.

En el siguiente ejemplo se combinan los módulos find con file. Con el primero
buscamos ficheros más antiguos de una semana y con el segundo los eliminamos.

Contenido del playbook.


- name: Eliminar ficheros antiguos de ~/Downloads
hosts: servidor
tasks:
- name: Obtiene la lista de ficheros más antiguos
find:
paths: ~/Downloads
age: 1w
recurse: yes
register: ficheros_antiguos - name: Elimina los
ficheros encontrados con find
file:
path: "{{ item.path }}"
state: absent
with_items: "{{ ficheros_antiguos.files }}"
Resultado al ejecutar el playbook anterior (en este ejemplo
elimina 3 ficheros encontrados).
PLAY [Eliminar ficheros antiguos de ~/Downloads] **********
TASK [Gathering Facts] ****
ok: [servidor]
TASK [Obtiene la lista de ficheros más antiguos] **********
ok: [servidor]
TASK [Elimina los ficheros encontrados con find] **********
changed: [servidor] => (item={u'uid': 0, u'woth': False, u'mtime':
1467808134.0234377, u'inode': 794739, u'isgid': False, u'size': 6108,
u'roth': True, u'isuid': False, u'isreg': True, u'gid': 0, u'ischr':
False, u'wusr': True, u'xoth': False, u'rusr': True, u'nlink': 1,
u'issock': False, u'rgrp': True, u'path':
u'/root/Downloads/download2.txt', u'xusr': False, u'atime':
1516700901.670455, u'isdir': False, u'ctime': 1520690442.0612476, u'wgrp':
False, u'xgrp': False, u'dev': 2050, u'isblk': False, u'isfifo': False,
u'mode': u'0644', u'islnk': False})
changed: [servidor] => (item={u'uid': 0, u'woth': False, u'mtime':
1466868336.5356927, u'inode': 791486, u'isgid': False, u'size': 49288366,
u'roth': True, u'isuid': False, u'isreg': True, u'gid': 0, u'ischr':
False, u'wusr': True, u'xoth': False, u'rusr': True, u'nlink': 1,

© Alfaomega-RC Libros 91
ANSIBLE

u'issock': False, u'rgrp': True, u'path': u'/root/Downloads/google-chrome-


stable_current_amd64.deb', u'xusr': False, u'atime': 1516700901.2224548,
u'isdir': False, u'ctime': 1466868336.5796928, u'wgrp': False, u'xgrp':
False, u'dev': 2050, u'isblk': False, u'isfifo': False, u'mode': u'0644',
u'islnk': False})
changed: [servidor] => (item={u'uid': 0, u'woth': False, u'mtime':
1467812530.1673994, u'inode': 795687, u'isgid': False, u'size': 4164,
u'roth': True, u'isuid': False, u'isreg': True, u'gid': 0, u'ischr':
False, u'wusr': True, u'xoth': False, u'rusr': True, u'nlink': 1,
u'issock': False, u'rgrp': True, u'path':
u'/root/Downloads/download1.csv', u'xusr': False, u'atime':
1516700901.6784549, u'isdir': False, u'ctime': 1520690430.7692478,
u'wgrp': False, u'xgrp': False, u'dev': 2050, u'isblk': False, u'isfifo':
False, u'mode': u'0644', u'islnk': False})

PLAY RECAP ****************


servidor : ok=3 changed=1 unreachable=0 failed=0

MÓDULO INI_FILE

Argumentos obligatorios
path=ruta Ruta al fichero con formato INI. Este
dest=ruta fichero puede ser creado si no existe.
section=sección Nombre de la sección en el fichero INI.
Argumentos permisos y Argumentos SELinux
Argumentos opcionales (Negrita indica el valor por defecto)
Argumentos Opciones Descripción
create yes Por defecto el fichero será creado
no si no existe.
no_extra_spaces No incluir espacios antes y despúes
del símbolo =.
option El nombre de la opción.
state present Si es establecido a absent se
absent borrará la opción o la sección. Con
present se crearán.
value El valor a ser asociado a la
opción.

En el siguiente ejemplo se modifica el fichero /etc/samba/smb.conf para


deshabilitar la navegación como anónimo en el directorio público.

92 © Alfaomega-RC Libros
CAPÍTULO 5: MÓDULOS

Cambiar valor dentro de smb.conf y reiniciar el servicio


smbd si se modifica.
- name: Deshabilitar la navegación como anónimo en PUB
hosts: servidor
tasks:
- ini_file:
path: /etc/samba/smb.conf
section: pub
option: guest ok
value: no
notify: restart_smbd
handlers:
- name: restart_smbd
service:
name: smbd
state: restarted

MÓDULO LINEINFILE

Argumentos obligatorios
path=ruta El fichero a modificar.
dest=ruta
destfile=ruta
name=ruta
Argumentos permisos y Argumentos SELinux
Argumentos opcionales (Negrita indica el valor por defecto)
Argumentos Opciones Descripción
backrefs no Especifica si la expresión puede
yes contener referencias anteriores.
create no Especifica si el fichero debe ser
yes creado si no existe.
insertafter EOF Si se especifica, se insertará
*regex* después de la línea encontrada con
dicha expresión. Si no se especifica
se insertará al final del fichero.
insertbefore BOF Si se especifica, se insertará antes
*regex* de la línea encontrada con dicha
expresión. Si no se especifica se
insertará al final del fichero.
line La línea a insertar o reemplazar.

© Alfaomega-RC Libros 93
ANSIBLE

regexp La expresión regular a buscar en cada


línea del fichero.
state present Indica si la línea debe estar en el
absent fichero o no.

En los siguientes ejemplos se muestran distintos escenarios donde el módulo


lineinfile tiene una gran utilidad.
Habilitar el puerto 8080 en la configuración de Apache
- name: Configurar el fichero ports.conf
hosts: servidor
tasks:
- name: Añadir la línea si no existe
lineinfile:
path: /etc/apache2/ports.conf
line: "Listen 8080"
insertafter: "^Listen 80$"
notify: restart_apache2
handlers:
- name: restart_apache2
service: name=apache2 state=restarted
Contenido del fichero ports.conf después de ejecutar el
playbook.
Listen 80
Listen 8080
<IfModule ssl_module>
Listen 443
</IfModule>
Playbook para establecer una línea del fichero de
configuración sshd buscando por una expresión.
- name: Configurar el fichero sshd_config
hosts: servidor
tasks:
- name: Editar configuración para mostrar el MOTD
lineinfile:
path: /etc/ssh/sshd_config
line: "PrintMotd yes"
regexp: "^PrintMotd"
notify: restart_sshd
handlers:
- name: restart_sshd
service: name=sshd state=restarted

94 © Alfaomega-RC Libros
CAPÍTULO 5: MÓDULOS

Ejecutando dicho playbook, con la opción --diff se mostrará


lo cambiado.
PLAY [Configurar el fichero sshd_config] **
TASK [Gathering Facts] ****
ok: [servidor]
TASK [Editar configuración para mostrar el MOTD] **********
--- before: /etc/ssh/sshd_config (content)
+++ after: /etc/ssh/sshd_config (content)
@@ -65,7 +65,7 @@
X11Forwarding yes
X11UseLocalhost no
X11DisplayOffset 10
-PrintMotd no
+PrintMotd yes
PrintLastLog yes
TCPKeepAlive yes
#UseLogin no
changed: [localhost]
RUNNING HANDLER [restart_sshd] ************
changed: [localhost]
PLAY RECAP ****************
servidor : ok=3 changed=2 unreachable=0 failed=0
Borrar una línea de un fichero sudoers.
- name: Eliminar permisos para el grupo %sudo
hosts: servidor
tasks:
- name: Eliminar la línea que empiece por %sudo
lineinfile:
path: /etc/sudoers
regexp: "^%sudo"
state: absent
Resultado de ejecución del playbook con la opción --diff
# ansible-playbook --diff lineinfile3.yml
PLAY [Eliminar permisos para el grupo %sudo] **************
TASK [Gathering Facts] ****
ok: [servidor]
TASK [Eliminar la línea que empiece por %sudo] ************
--- before: /etc/sudoers (content)
+++ after: /etc/sudoers (content)
@@ -20,7 +20,6 @@
rootALL=(ALL) ALL
# Allow members of group sudo to execute any command
-%sudoALL=(ALL:ALL) ALL

© Alfaomega-RC Libros 95
ANSIBLE

# See sudoers(5) for more information on "#include"


directives:
changed: [servidor]
PLAY RECAP ****************
servidor : ok=2 changed=1 unreachable=0 failed=0

MÓDULO REPLACE

Argumentos obligatorios
path=ruta El fichero a modificar.
dest=ruta
destfile=ruta
name=ruta
Argumentos permisos y Argumentos SELinux
Argumentos opcionales (Negrita indica el valor por defecto)
Argumentos Opciones Descripción
after Si se especifica, la línea a partir
de la cual la búsqueda se inicia para
reemplazar/eliminar.
before Si se especifica, la línea a partir
de la cual la búsqueda se termina
para reemplazar/eliminar.
encoding El juego de caracteres para
leer/escribir el fichero. Por defecto
utf-8.
follow no Indica si se debe seguir un enlace
yes simbólico.
regexp La expresión regular a buscar en el
contenido del fichero.
replace La cadena a reemplazar cuando la
expresión encuentra una coincidencia.

En el siguiente ejemplo renombramos todas las coincidencias de un dominio


por el nuevo dominio.

Contenido del playbook.


- name: Reemplazar un dominio por el nuevo
hosts: servidor
tasks:

96 © Alfaomega-RC Libros
CAPÍTULO 5: MÓDULOS

- name: Reemplazar oforte.net por rclibros.es


replace:
path: /etc/hosts
regexp: '(.*)?oforte\.net(.*)?$'
replace: '\1rclibros.es\2'
backup: yes
Resultado de la ejecución utilizando la opción --diff para
mostrar los cambios.
PLAY [Reemplazar un dominio por el nuevo] *****************
TASK [Gathering Facts] ****
ok: [servidor]
TASK [Reemplazar oforte.net por rclibros.es] **************
--- before: /etc/hosts
+++ after: /etc/hosts
@@ -1,7 +1,7 @@
127.0.0.1 localhost.localdomain localhost
::1 localhost localhost.localdomain localhost6
localhost6.localdomain6
-10.10.10.6 www.oforte.net ofortenet
-10.10.10.1 users users.oforte.net
-10.10.10.22 cloud cloud.oforte.net
+10.10.10.6 www.rclibros.es ofortenet
+10.10.10.1 users users.rclibros.es
+10.10.10.22 cloud cloud.rclibros.es
changed: [servidor]

PLAY RECAP ****************


servidor: ok=2 changed=1 unreachable=0 failed=0

MÓDULO STAT
Argumentos obligatorios
path=ruta La ruta entera al
fichero/objeto para obtener
información.
Argumentos opcionales (Negrita indica el valor por defecto)
Argumentos Opciones Descripción
checksum_algorithm sha1 Algoritmo a determinar el
checksum sha224 checksum del fichero.
checksum_algo sha256
sha384
sha512

© Alfaomega-RC Libros 97
ANSIBLE

follow no Indica si se debe seguir un


yes enlace simbólico.
get_attributes yes Obtiene los atributos usando
attr no la herramienta lsattr.
attributes
get_checksum yes Si debe obtener el checksum
no del fichero. Por defecto
sha1.
get_md5 yes Si debe devolver el valor md5
no del fichero.
get_mime yes Indica si debe devolver el
mimemime_type no valor file magic utilizando
mime-type la utilidad file.

En el siguiente ejemplo obtenemos la información del fichero /etc/services y


mostramos su permiso y el tamaño.

Contenido del playbook utilizando el módulo stat para


obtener la información y debug para mostrar la información.
- name: Obtener información usando stat
hosts: servidor
tasks:
- name: Obtener información del fichero /etc/services
stat:
path: /etc/services
register: info_services
- debug:
msg: |
El fichero /etc/services tiene permiso {{
info_services.stat.mode }}
y su tamaño es {{ info_services.stat.size }} bytes

Mensaje mostrado al ejecutar el playbook.


TASK [debug] **************
ok: [servidor] => {
"msg": "El fichero /etc/services tiene permiso 0644\ny su
tamaño es 19605 bytes\n"
}

98 © Alfaomega-RC Libros
CAPÍTULO 5: MÓDULOS

MÓDULO TEMPLATE

Argumentos obligatorios
src=ruta Ruta al fichero con formato Jinja2 en
el servidor que ejecuta Ansible. Puede
ser una ruta relativa o absoluta.
dest=ruta Lugar de destino donde la plantilla
renderizada será copiada.
Argumentos permisos y Argumentos SELinux
Argumentos opcionales (Negrita indica el valor por defecto)
Argumentos Opciones Descripción
block_end_string Marca indicando el final de
un bloque. Por defecto: %}
block_start_string Marca indicando el inicio de
un bloque. Por defecto: {%
follow no Indica si se deben seguir los
yes enlaces simbólicos.
force yes Por defecto se reemplaza el
no contenido del fichero
destino,en caso contrario
solo se copiará si el destino
no existe.
newline_sequence \n Secuencia de caracteres para
\r indicar nueva línea.
\r\n
trim_blocks no Indica si la primera nueva
yes línea después de un bloque
debe ser eliminada.
variable_end_string Marca indicando el final de
una sentencia de
visualización. Por defecto }}
variable_start_string Marca indicando el inicio de
una sentencia de
visualización. Por defecto {{

En el siguiente ejemplo utilizamos una plantilla para generar información de


utilidad dentro del fichero /etc/issue:

© Alfaomega-RC Libros 99
ANSIBLE

Plantilla (issue.j2) utilizada para generar /etc/issue.


System Information For Hostname: {{ inventory_hostname }}
Distribution: {{ ansible_distribution }}
Distribution Release: {{ ansible_distribution_release }}
Distribution Version: {{ ansible_distribution_version }}
IP Address: {{ ansible_default_ipv4.address }}
DNS Server(s): {{ ansible_dns.nameservers|join (" ") }}
Kernel: {{ ansible_kernel }}
{% if ansible_lsb is defined %}
LSB: {{ ansible_lsb.description }}
{% endif %}
Memory Installed: {{ (ansible_memtotal_mb / 1024) | round(1) }}GB
Memory Swapfile: {{ (ansible_swaptotal_mb / 1024) | round(1) }}GB
Processors: {{ ansible_processor_vcpus }}
Playbook para utilizar plantilla para generar /etc/issue.
- name: Generar el contenido del fichero /etc/issue
hosts: servidor
tasks:
- template:
src: issue.j2
dest: /etc/issue
Resultado ejemplo del fichero generado.
# cat /etc/issue
System Information For Hostname: cloud.oforte.net
Distribution: Debian
Distribution Release: jessie
Distribution Version: 8
IP Address: 91.121.79.141
DNS Server(s): 213.186.33.99 10.10.10.6
Kernel: 3.16.0-4-amd64
LSB: Debian GNU/Linux 8.10 (jessie)
Memory Installed: 15.7GB
Memory Swapfile: 0.5GB
Processors: 8

MÓDULO UNARCHIVE

Argumentos obligatorios
src=ruta Ruta del fichero a descomprimir.
dest=ruta Ruta absoluta del directorio donde los
ficheros deben ser descomprimidos.

100 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

Argumentos permisos y Argumentos SELinux


Argumentos opcionales (Negrita indica el valor por defecto)
Argumentos Opciones Descripción
creates Un fichero, que si existe, la tarea
no se ejecutará.
decrypt yes Esta opción indica si debe
no descifrarse automáticamente
utilizando Vault.
exclude Lista de directorios y ficheros que
deben ser excluidos al extraer.
extra_opts Especifica opciones adicionales para
descomprimir.
keep_newer no Indica si reemplaza los ficheros
yes existentes más nuevos que los del
archivo.
list_files no Si se activa, devuelve la lista de
yes ficheros extraídos.
remote_src no Indica si el fichero está en el nodo
yes remoto administrado (yes) o debe ser
copiado desde donde se ejecuta (no).

En el siguiente ejemplo transferimos desde el servidor donde ejecutamos


Ansible al nodo administrado un fichero y lo descomprimimos. Con el módulo
debug mostramos el directorio donde lo extraemos y el primer directorio del
contenido del fichero para indicar dónde está el contenido.

Contenido del playbook para extraer un fichero en el nodo.


- name: Copiar fichero comprimido al nodo y extraerlo
hosts: servidor
tasks:
- name: Extraer la versión de ansible 2.4.3.0
unarchive:
src: v2.4.3.0-1.tar.gz
dest: /usr/local/src/
list_files: True
register: lista_ficheros
- debug: msg="Extraído en {{ lista_ficheros.dest }}/{{
lista_ficheros.files[0] }}"

© Alfaomega-RC Libros 101


ANSIBLE

Mensaje mostrado al ejecutar el playbook.


ok: [servidor] => {
"msg": "Extraído en /usr/local/src//ansible-2.4.3.0-1/"
}

MÓDULOS DE GESTOR DE PAQUETES


Estos módulos permiten trabajar con gestores de paquetes de dos tipos:
lenguajes de programación y de sistemas operativos/distribuciones.

Módulos para gestionar paquetes de lenguaje de programación


(en negrita los detallados en este libro).
bower Administra paquetes para desarrollo web.
bundler Administra dependencias de Ruby Gem.
composer Gestiona librerías PHP.
cpanm Gestiona módulos de Perl (CPAN).
easy_install Gestiona módulos/librerías del lenguaje
Python.
gem Gestiona Ruby Gems.
maven_artifact Descarga artifacts desde un repositorio
Maven.
npm Gestiona paquetes de node.js con npm
pear Gestiona paquetes de pear/pcl.
pip Gestiona módulos/librerías del lenguaje
Python.
Módulos para gestionar paquetes del sistema
operativo/distribuciones (en negrita los detallados).
apk Gestiona paquetes de Android.
apt Gestiona paquetes APT para
apt_key distribuciones: Debian, Ubuntu, etc…

apt_repository
apt_rpm
dnf Gestiona paquetes de la distribución
Fedora.
dpkg_selections Gestiona selección de paquetes dpkg

102 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

homebrew Gestor de paquetes para Homebrew


homebrew_cask Instalar/desinstalar homebrew casks.
homebrew_tap Tap un repositorio de Homebrew.
layman Gestionar overlays de Gentoo.
macports Gestiona paquetes del repositorio
MacPorts.
openbsd_pkg Gestiona paquetes del sistema operativo
OpenBSD.
opkg Gestiona paquetes de OpenWRT.
package Gestiona paquetes genéricos (es un
wrapper).
pacman Gestiona paquetes de Arch Linux.
pkg5 Gestiona paquetes del sistema operativo
Solaris 11.
pkgin Gestor de paquetes SmartOS, NetBSD y
otros.
pkgng Gestor de paquetes FreeBSD >= 9.0.
pkgutil Gestor de paquetes CSW en Solaris.
portage Gestor de paquetes en Gentoo.
portinstall Instala paquetes desde el sistema de
"ports" de FreeBSD.
pulp_repo Añade o elimina repositorios de pulp en
el nodo administrado.
Administra suscripciones y registros a
redhat_subscription RHSM usando el comando subscription-
manager.
rhn_channel Añade o elimina canales de software de
Red Hat.
rhn_register Administra el registro a la red de Red
Hat utilizando el comando rhnreg_ks.
rpm_key Añade o elimina claves gpg desde la
base de datos RPM.
slackpkg Gestiona paquetes en Slackware >= 12.2.
sorcery Gestiona paquetes de Source Mage
GNU/Linux.
svr4pkg Gestiona paquetes de Solaris SVR4.

© Alfaomega-RC Libros 103


ANSIBLE

swdepot Gestiona paquetes con swdepot (HP-UX).


swupd Gestiona actualizaciones y bundles en
sistemas ClearLinux.
urpmi Gestor de urpmi.
xbps Gestiona paquetes con XBPS.
yum Gestiona paquetes con YUM.
yum_repository Añade o elimina repositorios YUM.
zypper Gestiona paquetes en SUSE y openSUSE.
zypper_repository Añade y elimina repositorios Zypper.

MÓDULO CPANM

Para utilizar este módulo debemos instalar el paquete cpanminus en


Debian/Ubuntu o perl-App-cpanminus en CentOS/Red Hat.

Argumentos opcionales
executable Sobrescribe la ruta del ejecutable de
cpanm.
from_path El directorio local donde instalar el
módulo.
installdeps Instala solo dependencias.
locallib Especifica el directorio base a instalar
los módulos.
mirror Especifica la dirección URL (mirror) de
CPAN a utilizar.
mirror_only Utiliza el índice del fichero mirror en
vez del CPAN Meta DB.
namepkg El nombre de la librería Perl a instalar.
notest No ejecuta los tests unitarios.
system_libuse_sudo Indica si se debe instalar en la ruta de
módulos global del sistema.
version Mínima versión del módulo aceptada para
que pueda ser instalado el módulo.

En el siguiente ejemplo instalamos el módulo Text::CSV utilizando CPAN. Este


módulo es usado para tratar ficheros CSV.

104 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

Comprobamos que el módulo no está instalado.


# perl -le 'use Text::CSV;'
Can't locate Text/CSV.pm in @INC (you may need to install the Text::CSV
module) (@INC contains: /etc/perl /usr/local/lib/x86_64-linux-
gnu/perl/5.20.2 /usr/local/share/perl/5.20.2 /usr/lib/x86_64-linux-
gnu/perl5/5.20 /usr/share/perl5 /usr/lib/x86_64-linux-gnu/perl/5.20
/usr/share/perl/5.20 /usr/local/lib/site_perl .) at -e line 1.

Contenido del playbook utilizando el módulo cpanm.


- name: Instalar el módulo Text::CSV.
hosts: servidor
tasks:
- name: Instalar cpanminus en Debian
apt:
name: cpanminus
state: present
- name: Instalar el módulo Text::CSV
cpanm:
name: Text::CSV
Ejecutar el playbook y comprobar que se puede utilizar el
módulo Text::CSV.
# ansible-playbook cpanm.yml
PLAY [Instalar el módulo Text::CSV] ********
TASK [Gathering Facts] ****
ok: [servidor]
TASK [Instalar cpanminus en Debian] *******
changed: [servidor]
TASK [Utilizar cpanm para instalar el módulo Text::CSV] ***
changed: [servidor]

PLAY RECAP ****************


localhost : ok=3 changed=2 unreachable=0 failed=0

# perl -le 'use Text::CSV;'


#

MÓDULO EASY_INSTALL

Argumentos obligatorios
name=nombre El nombre de la librería Python a
instalar.

© Alfaomega-RC Libros 105


ANSIBLE

Argumentos opcionales (Negrita indica el valor por defecto)


Argumentos Opciones Descripción
executable La ruta explicita al
ejecutable easy_install.
state present El estado deseado de la
latest librería. Con latest asegura
que la última versión está
instalada.
virtualenv Opcionalmente un entorno
virtual a instalar la
librería.
virtualenv_command virtualenv El comando a utilizar para
virtualenv2 crear el entorno virtual.
pyenv
virtualenv_site_packages no Indica si el entorno virtual
yes incluirá los paquetes del
directorio global del
sistema.

En el siguiente ejemplo se utiliza easy_install (que es una utilidad que viene


por defecto en la instalación de Python) para instalar PIP, que es un gestor más
moderno y potente.

Contenido del playbook.


- name: Instalar PIP usando easy_install
hosts: servidor
tasks:
- name: Instalar pip
easy_install:
name: pip
state: latest

MÓDULO PEAR

Argumentos obligatorios
name=nombre Nombre del paquete a instalar, actualizar
o borrar.

106 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

Argumentos opcionales (Negrita indica el valor por defecto)


Argumentos Opciones Descripción
executable Ruta de ejecutable pear.
state present Estado deseado del paquete.
absent
latest

En el siguiente ejemplo instalamos la librería Date usando Pear.


Contenido del playbook, primero se instala php-pear y luego
la librería Date.
- name: Instalar paquete Date desde Pear
hosts: servidor
tasks:
- name: Instalar paquete php-pear en Debian/Ubuntu
apt:
name: php-pear
- name: Instalar Date usando pear
pear:
name: Date

MÓDULO PIP

Argumentos opcionales (Negrita indica el valor por defecto)


chdir Cambia a dicho directorio
antes de ejecutar el
comando.
editable Establece el valor de
editable.
executable Ruta donde pip se
encuentra.
extra_args Argumentos extra pasados a
pip.
name Nombre de la librería
Python a instalar o
eliminar.
requirements La ruta a un fichero de
requisitos, que contiene la
lista de módulos a
instalar.

© Alfaomega-RC Libros 107


ANSIBLE

state present El estado del módulo.


absent
latest
forcereinstall

umask La máscara de usuario del


sistema antes de instalar
el paquete pip.
version La versión del paquete a
instalar del módulo.
virtualenv Opcionalmente el directorio
del entorno virtual donde
instalar la librería.
virtualenv_command virtualenv El comando o la ruta para
virtualenv2 crear el entorno virtual.
pyenv
virtualenv_python La ruta de Python para
crear el entorno virtual.
virtualenv_site_package no Indica si el entorno
s yes virtual incluirá los
paquetes del directorio
global del sistema.

En los siguientes ejemplos, instalamos un paquete individual y una lista de


módulos indicados en un fichero.

Instalar el módulo requests utilizando pip


- name: Instalar el módulo requests
hosts: servidor
tasks:
- name: Instalar requests
pip:
name: requests
state: present

El contenido del fichero requirements.txt

lxml
pyOpenSSL
parsel>=1.4

108 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

Instalar lista de módulos definidos en un fichero de


requirements.
- name: Instalar módulos definidos en requirements.txt
hosts: servidor
tasks:
- name: Instalar lista de requisitos
pip:
requirements: requirements.txt

MÓDULO APT

Argumentos opcionales (Negrita indica el valor por defecto)


Argumentos Opciones Descripción
allow_unauthentica no Ignora paquetes que no puedan
ted yes ser autenticados.
autoclean no Indica si debe eliminarse el
yes repositorio local donde los
ficheros están descargados.
autoremove no Indica si se deben eliminar
yes las dependencias que no están
en uso.
cache_valid_time Actualiza el caché de apt si
es más antiguo que
cache_valid_time.
deb Ruta al fichero .deb en el
nodo remoto. Si incluye ://
intentará descargarlo antes
de instalarlo.
default_release Corresponde a la opción -t
del comando apt.
dpkg_options Opciones para el comando
dpkg.
force no Indica si debe forzar la
yes instalación/eliminación.
force_apt_get Fuerza el uso de apt-get en
vez de aptitude.
install_recommends no Corresponde a la opción --no-
yes install-recommends de apt.

© Alfaomega-RC Libros 109


ANSIBLE

namepkgpackage El nombre del paquete o el


conjunto de paquete y versión
(paquete=1.0)
only_upgrade Actualiza solo un paquete si
está instalado.
purge no Forzará la eliminación de los
yes ficheros de configuración
cuando el state es absent.
state latest Indica el estado deseado del
absent paquete.
present
build-dep
update_cache no Ejecuta el equivalente de
yes apt-get update antes de la
operación.
upgrade no Si yes o safe, realiza un
yes aptitude safe-upgrade.Si
safe full, realiza un aptitude
fulldist full-upgrade. Si dist,
realiza un apt-get dist-
upgrade.

En la siguiente tabla se muestran tareas comunes que se realizan con el


comando apt-get/aptitude.
Instalar el paquete lftp (igual que apt-get install lftp)
- name: Instalar lftp usando apt
hosts: servidor
tasks:
- name: Instalar la última versión de lftp
apt:
name: lftp
state: latest
update_cache: True
Eliminar el paquete lftp (igual que apt-get remove -y lftp)
- name: Asegurarse de que lftp no está instalado
hosts: servidor
tasks:
- name: Desinstalar lftp si está instalado
apt:
name: lftp
state: absent

110 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

Actualizar todos los paquetes del sistema (apt-get upgrade)


- name: Actualizar los paquetes del sistema de forma segura
hosts: servidor
tasks:
- name: Actualizar paquetes
apt:
upgrade: dist

MÓDULO APT_KEY

Argumentos opcionales (Negrita indica el valor por defecto)


Argumentos Opciones Descripción
data El contenido de la clave al
llavero de claves.
file La ruta del fichero con la clave
en el nodo remoto a añadir en el
llavero de claves.
id El identificador de la clave.
Este argumento es obligatorio
cuando state es establecido a
absent.
keyring La ruta del fichero llavero de
claves en
/etc/apt/trusted.gpg.d/
keyserver El servidor de claves de onde
recibir la clave.
state present Asegura que la clave está
absent añadida (present) o revocada
(absent).
url La dirección URL donde obtener
la clave.
validate_certs yes Indica si el certificado SSL de
no la URL indicada debe ser
comprobado para su validez.

En el siguiente ejemplo se descarga y acepta la clave pública del repositorio


oficial de Debian para la versión 9 (stretch):

© Alfaomega-RC Libros 111


ANSIBLE

Playbook para añadir las claves de stretch


- name: Añadir claves de apt
hosts: servidor
tasks:
- apt_key:
url: "{{ item }}"
state: present
with_items:
- https://ftp-master.debian.org/keys/archive-key-9.asc
- https://ftp-master.debian.org/keys/archive-key-9-security.asc

MÓDULO APT_REPOSITORY

Este módulo creará un fichero dentro del directorio /etc/apt/sources.list.d/


con el repositorio especificado.

Argumentos obligatorios
repo=repositorio El repositorio a utilizar.
Argumentos opcionales (Negrita indica el valor por defecto)
Argumentos Opciones Descripción
codename Sobrescribe el código de la
distribución a ser utilizada en
los repositorios PPA.
filename Establece el nombre del fichero
dentro del directorio
sources.list.d. La extensión
.list se añadirá
automáticamente.
mode El modo octal del fichero nuevo
creado, por defecto 644.
state present El estado deseado.
absent
update_cache yes Ejecuta el equivalente de apt-
no get update cuando un cambio
ocurre.
validate_certs yes Indica si el certificado SSL de
no la URL indicada debe ser
comprobado para su validez.

112 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

En el siguiente ejemplo añadimos el repositorio oficial de Google Chrome:


Playbook para configurar el repositorio.
- name: Añadir repositorio de google chrome
hosts: servidor
tasks:
- apt_repository:
repo: deb http://dl.google.com/linux/chrome/deb/ stable main
state: present
filename: 'google-chrome'
update_cache: True
Comprobación de fichero creado dentro de
/etc/apt/sources.list.d/ después de ejecutarlo.
# ls -l /etc/apt/sources.list.d/google-chrome.list
-rw-r--r-- 1 root root 55 Mar 10 20:46 /etc/apt/sources.list.d/google-
chrome.list
# cat /etc/apt/sources.list.d/google-chrome.list
deb http://dl.google.com/linux/chrome/deb/ stable main

MÓDULO DNF
Argumentos obligatorios
name=paquete Nombre del paquete o combinación de
paquete y versión (nombre-1.). Con el
valor "*" actualizará todos los paquetes.
Es posible especificar una ruta de fichero
o una dirección url.
Argumentos opcionales (Negrita indica el valor por defecto)
Argumentos Opciones Descripción
autoremove no Si se habilita esta opción se
yes eliminarán las dependencias
instaladas que ya no están en
uso.
conf_file El fichero de configuración
remota a ser utilizada.
disable_gpg_check no Indica si se debe deshabilitar la
yes comprobación GPG.
disablerepo Identificador del repositorio a
deshabilitar durante una
operación de instalación o
actualización.

© Alfaomega-RC Libros 113


ANSIBLE

enablerepo Identificador del repositorio a


habilitar durante una operación
de instalación o actualización.
installroot Especifica un directorio raíz
donde el paquete será instalado.
state present Si debe ser instalado (present,
latest latest), o eliminado (absent).
absent

En los siguientes ejemplos se muestran tareas comunes que se realizan con


dnf.

Instalar lftp usando dnf (dnf install lftp).


- name: Instalar lftp en nodo fedora
hosts: fedora
tasks:
- name: Instalar la última versión de lftp
dnf:
name: lftp
state: latest
Actualizar el sistema (dnf update).
- name: Actualizar paquetes a la última versión
hosts: fedora
tasks:
- name: Actualizar todos los paquetes
dnf:
name: "*"
state: latest

MÓDULO PACKAGE

Argumentos obligatorios
name=paquete Nombre del paquete o combinación de nombre y
versión (paquete-1.0).
state=estado present Si debe ser instalado (present,
latest latest), o eliminado (absent).
absent
Argumentos opcionales (Negrita indica el valor por defecto)

114 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

Argumentos Opciones Descripción


use auto El gestor de paquetes a utilizar
(yum, apt, etc.)

El siguiente playbook instala chrony usando el módulo package, no teniendo


que distinguir qué gestor de paquetes utilizar (apt, yum, dnf, etc.). Para sistemas
Windows es necesario utilizar el módulo win_package.

Contenido del playbook.


- name: Instalar chrony usando el módulo package
hosts: servidor
tasks:
- name: Instalar chrony
package:
name: chrony
state: latest

MÓDULO PACMAN

Argumentos opcionales (Negrita indica el valor por defecto)


force no Cuando se elimina un paquete,
yes fuerza la eliminación sin
realizar comprobaciones.
namepkgpackage Nombre del paquete a instalar,
actualizar o eliminar.
recurse no Cuando se elimina un paquete,
yes eliminar también las
dependencias.
state present El estado deseado del paquete.
absent
latest
update_cacheupdate- no Indica si actualizar o no la
cache yes lista de paquetes del sistema.
upgrade no Si se debe actualizar todo el
yes sistema o no.

En los siguientes ejemplos hacemos tareas comunes con pacman.

© Alfaomega-RC Libros 115


ANSIBLE

Instalar o actualizar a la última version de lftp usando


pacman (pacman -S lftp).
- name: Instalar lftp usando pacman
hosts: gentoo
tasks:
- name: Instalar lftp
pacman:
name: lftp
state: latest
Desinstalar lftp (pacman -R lftp).
- name: Desinstalar lftp usando pacman
hosts: gentoo
tasks:
- name: Desinstalar lftp
pacman:
name: lftp
state: absent
Actualizar todos los paquetes del sistema a la última
versión (pacman -Su).
- name: Actualizar los paquetes a la última versión
hosts: gentoo
tasks:
- name: Actualizar todos los paquetes del sistema
pacman:
upgrade: yes

MÓDULO YUM

Argumentos obligatorios
name=paquete Nombre del paquete o combinación de nombre
pkg=paquete y versión (paquete-1.0).
Argumentos opcionales (Negrita indica el valor por defecto)
Argumentos Opciones Descripción
allow_downgrade no Especifica si es posible
yes instalar una versión más antigua
que la instalada en el nodo
remoto.
conf_file Ruta al fichero de configuración
de yum.

116 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

disable_gpg_check no Indica si se debe deshabilitar


yes la comprobación GPG.
disablerepo Identificador del repositorio a
deshabilitar durante una
operación de instalación o
actualización.
enablerepo Identificador del repositorio a
habilitar durante una operación
de instalación o actualización.
exclude Nombre de paquete(s) a ser
excluido cuando state=présent o
state=latest.
installroot Especifica un directorio raíz
donde el paquete será instalado.
list Nombre del paquete a ejecutar el
equivalente de yum list paquete.
security no Si se establece a yes y
yes state=latest entonces solo
instala actualizaciones que han
sido de tipo seguridad.
skip_broken no Resuelve problemas de
yes dependencias eliminando los
paquetes que causan problemas.
state present Si debe instalarse (present or
installed installed, latest) o eliminarse
latest (absent or removed).
absent
removed
update_cacheexpire- no Fuerza a yum a comprobar si el
cache yes caché está expirado y lo
descarga si es necesario.
validate_certs yes Indica si el certificado SSL de
no la URL indicada debe ser
comprobado para su validez.

En los siguientes ejemplos se muestran las tareas más comunes que se realizan
con yum.

© Alfaomega-RC Libros 117


ANSIBLE

Instalar paquetes para LAMP (Linux, Apache, MySQL, PHP).


- name: Instalar paquetes con yum
hosts: servidor
tasks:
- name: Instalar paquetes para LAMP
yum:
name: "{{ item }}"
state: present
with_items:
- mariadb-server
- mariadb
- httpd
- php
Desinstalar un paquete (yum remove chrony).
- name: Desinstalar chrony
hosts: servidor
tasks:
- name: Borrar chrony usando yum
yum:
name: chrony
state: absent
Actualizar los paquetes del sistema a la última versión
(yum update) excepto el kernel.
- name: Actualizar todos los paquetes menos kernel
hosts: servidor
tasks:
- name: Actualizar paquetes excluyendo el kernel
yum:
name: '*'
state: latest
exclude: kernel*

MÓDULO YUM_REPOSITORY

Argumentos obligatorios
name=repositorio Identificador del repositorio.
Argumentos opcionales (Negrita indica el valor por defecto)
[más utilizados, no todos]
baseurl Dirección URL donde está el
repositorio.

118 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

description Una descripción del repositorio.


enabled yes Indica si debe estar habilitado
no o no.
file Fichero a usar donde guardar el
repositorio.
gpgcheck yes Indicado si yum debe comprobar
no la firma GPG.
gpgkey Una dirección URL que apunta al
fichero con la clave GPG.
mirrorlist Especifica una URL a un fichero
que contiene una lista de
baseurls.
params Opción usada para permitir al
usuario sobrescribir cualquier
opción.
skip_if_unavailable no Si se habilita esta opción, yum
yes continuará incluso que alguno de
los repositorios no esté
disponible.
state present Estado del fichero del
absent repositorio.

En los siguientes ejemplos mostramos la manera de añadir/activar repositorios


comunes.
Añadir el repositorio EPEL.
- name: Añadir el repositorio EPEL
hosts: servidor
tasks:
- name: Añadir repositorio
yum_repository:
name: epel
description: Repositorio EPEL YUM
baseurl: https://download.fedoraproject.org/pub/epel/$releasever/$basearch/
Añadir el repositorio para VirtualBox.
- name: Añadir el repositorio VirtualBox
hosts: servidor
tasks:
- name: Añadir repositorio
yum_repository:

© Alfaomega-RC Libros 119


ANSIBLE

name: virtualbox
description: Oracle Linux / RHEL / CentOS-$releasever / $basearch -
VirtualBox
baseurl: http://download.virtualbox.org/virtualbox/rpm/el/$releasever/$basearch
enabled: True
gpgcheck: True
repo_gpgcheck: true
gpgkey: https://www.virtualbox.org/download/oracle_vbox.asc

MÓDULO REDHAT_SUBSCRIPTION
Argumentos opcionales (Negrita indica el valor por defecto)
Argumentos Opciones Descripción
activationkey Indica una clave de activación a
ser utilizada durante el registro.
autosubscribe Después de un registro correcto,
autoconsume las suscripciones
disponibles.
consumer_id Referencia a un ID de cliente para
continuar el registro anterior de
un sistema.
consumer_name Nombre del sistema a registrar,
por defecto el nombre del nodo.
consumer_type El tipo de unidad a registrar, por
defecto un sistema.
environment Registra con un entorno específico
en la organización destino. Usada
con Red Hat Satellite 6.x o
Katello.
force_register Registra el sistema incluso si
está registrado.
org_id ID de la organización a ser
utilizada en conjunción con la
clave de activación
(activationkey).
password Contraseña de access.redhat.com o
de Satellite 6.
pool Especifica el nombre del pool a
consumir. Expresiones regulares
son aceptadas.

120 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

pool_ids Especifica el ID del pool a


consumir. Más rápido que utilizar
pool.
rhsm_baseurl Especifica la URL base para el
CDN.
server_hostname Especifica un servidor alternativo
para Red Hat Subscription
Management o servidor Satellite
6.X.
server_insecure Habilita o deshabilita la
verificación de certificados del
servidor cuando se conecta a
server_hostname.
server_proxy_ho Especifica un servidor un HTTP
stname proxy
server_proxy_pa Especifica una contraseña para el
ssword HTTP proxy.
server_proxy_po Especifica el puerto para el HTTP
rt proxy.
server_proxy_us Especifica un usuario a usar para
er el HTTP proxy.
state present Si se debe registrar y suscribir
absent (present), o desregistrar (absent)
un sistema.
username Usuario para access.redhat.com o
Satellite 6.x

En los siguientes ejemplos se muestra cómo suscribirse utilizando Red Hat


Subscription Manager o usando Satellite 6.

Suscribirse utilizando RHSM.


- name: Registrar a la red de Red Hat
hosts: redhat
tasks:
- redhat_subscription:
state: present
username: usuario@dominio.com
password: clave
autosubscribe: true

© Alfaomega-RC Libros 121


ANSIBLE

Suscribirse utilizando Satellite 6.


- name: Registrar contra el servidor Satellite 6
hosts: redhat
tasks:
- name: Instalar katello-ca RPM para usar satellite
yum:
name: http://sat6 /pub/katello-ca-consumer-latest.noarch.rpm
state: present
- name: Registrarse usando Sat 6 y usar las suscripciones de RHEL y RHV
redhat_subscription:
state: present
activationkey: act-rhv-7.4
org_id: 1
pool: '^(Red Hat Enterprise Server|Red Hat Virtualization)$'

MÓDULO ZYPPER

Argumentos obligatorios
name=paquete Nombre del paquete o combinación de
nombre y versión (paquete-1.0).
Argumentos opcionales (Negrita indica el valor por defecto)
disable_gpg_ch no Indica si se debe deshabilitar
eck yes la comprobación GPG.
disable_recomm yes Corresponde a la opción --no-
ends no recommends de zypper.
extra_args Añade opciones adicionales al
comando zypper
force no Añade la opción --force al
yes comando zypper.
oldpackage no Añade la opción --oldpackage al
yes comando zypper.
state present Indica el estado deseado del
latest paquete.
absent
dist-upgrade
type package El tipo de paquete a ser
patch administrado.
pattern
product

122 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

srcpackage
application
update_cachere no Ejecuta el equivalente a zypper
fresh yes refresh.

En los siguientes ejemplos mostramos las tareas más comunes realizadas con
el comando zypper:

Instalar lftp usando zypper (zypper install lftp.


- name: Instalar lftp
hosts: servidorsuse
tasks:
- zypper:
name: lftp
state: present
Desinstalar el paquete ntp (zypper remove ntp).
- name: Eliminar ntp
hosts: servidorsuse
tasks:
- zypper:
name: ntp
state: absent
Actualizar todos los paquetes a su última versión (zypper
update).
- name: Actualizar todos los paquetes a su última versión
hosts: servidorsuse
tasks:
- zypper:
name: "*"
state: latest

MÓDULO ZYPPER_REPOSITORY

Argumentos opcionales (Negrita indica el valor por defecto)


Argumentos Opciones Descripción
auto_import_keys no Automáticamente importa la clave
yes de firmado gpg en un repositorio
nuevo o modificado.

© Alfaomega-RC Libros 123


ANSIBLE

autorefreshrefresh yes Habilita autorefresh en el


no repositorio.
description Una descripción del repositorio.
disable_gpg_check no Indica si se debe deshabilitar
yes la comprobación GPG.
enabled yes Habilita el repositorio o lo
no deshabilita.
name El nombre del repositorio. No es
requerido cuando se añaden
ficheros del repositorio.
overwrite_multiple no Sobrescribe múltiples entradas
yes del repositorio.
priority Establece la prioridad del
repositorio.
repo URL del repositorio o el fichero
.repo.
runrefresh no Refresca la lista de paquetes
yes del repositorio dado.
state present El estado deseado del
absent repositorio.

En el siguiente ejemplo utilizamos el módulo zypper_repository para añadir el


repositorio oficial de ownCloud.
Contenido del playbook.
- name: Añadir repositorios de ownCloud
hosts: servidor
tasks:
- zypper_repository:
name: owncloud-repo
repo: http://download.owncloud.org/openSUSE_Leap_42.3/
state: present
Contenido fichero generado: /etc/zypp/repos.d/owncloud-
repo.repo.
[owncloud-repo]
enabled=1
autorefresh=1
baseurl=http://download.owncloud.org/openSUSE_Leap_42.3/
type=rpm-md
gpgcheck=1

124 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

MÓDULOS PARA EJECUTAR COMANDOS


Estos módulos permiten ejecutar comandos en el nodo administrado:
command Ejecuta un comando en un nodo remoto (de forma más
segura).
expect Ejecuta un comando y responde a las preguntas del
mismo.
raw Ejecuta comandos a bajo nivel (de forma menos
segura).
script Ejecuta un script local en un nodo remoto después
de transferirlo.
shell Ejecuta comandos en un nodo remoto usando la shell.
telnet Ejecuta comandos a bajo nivel usando telnet (muy
inseguro).

MÓDULO COMMAND

Argumentos obligatorios
comando El comando a ejecutar en el nodo.
Argumentos opcionales
chdir Cambia a este directorio antes de ejecutar el
comando.
creates Fichero que cuando existe la tarea no se ejecutará.
removes Fichero que cuando NO existe la tarea NO se
ejecutará.
stdin Establece la entrada por defecto del comando
directamente usando este valor.

En los siguientes ejemplos vemos cómo utilizar algunos de los argumentos.

Leer el fichero resolv.conf y mostrarlo en pantalla.


- name: Leer el contenido del fichero resolv.conf
hosts: servidor
tasks:
- name: Ejecutar cat
command: cat /etc/resolv.conf
register: resolv_conf
- debug: var=resolv_conf.stdout

© Alfaomega-RC Libros 125


ANSIBLE

Cambiar el directorio y hacer una copia de seguridad solo


si el fichero destino no existe (usando creates).
- name: Hacer copia de seguridad del directorio /etc/
hosts: servidor
tasks:
- command: tar -ccvzf etc-{{ ansible_date_time.date }}.tar.gz /etc
args:
chdir: /var/backups
creates: /var/backups/etc-{{ ansible_date_time.date }}.tar.gz
Inicializar el servidor web solo cuando un fichero exista
(usando removes).
- name: Arrancar el servidor web sólo cuando un fichero exista
hosts: servidor
tasks:
- command: systemctl start httpd
args:
removes: /etc/apache2/ports.conf

MÓDULO EXPECT

Argumentos obligatorios
command=comando El comando a ejecutar en el nodo.
responses=lista Tabla de preguntas esperadas y respuestas a
proporcionar.
Argumentos opcionales
chdir=directorio Cambia a este directorio antes de ejecutar
el comando.
creates=fichero Fichero que cuando existe la tarea no se
ejecutará.
echo=yes/no Indica si debe mostrar las respuestas en
pantalla.
removes=fichero Fichero que cuando NO existe la tarea NO se
ejecutará.
timeout=segundos Cantidad máxima a esperar por las preguntas
esperadas. Por defecto 30.

En el siguiente ejemplo cambiamos la contraseña de un usuario. Se instala la


librería Python de pexpect para poder utilizar el módulo de Ansible.

126 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

Ejecutar el comando passwd y responder a las dos preguntas


(pedir clave y confirmar clave). Debe ser root.
- name: Cambiar contraseña de usuario
hosts: servidor
tasks:
- name: Instalar libreria pexpect
pip:
name: pexpect
state: latest
- name: Cambiar contraseña
expect:
command: passwd alberto
responses:
"Enter new UNIX password:": "Start123$"
"Retype new UNIX password:": "Start123$"

MÓDULO RAW
Argumentos obligatorios
comando El comando a ejecutar en el nodo.
Argumentos opcionales (Negrita indica el valor por defecto)
executable Ruta absoluta de la shell a utilizar para
ejecutar el comando.

En el siguiente ejemplo ejecutamos un comando directamente en el servidor


sin asegurar la entrada (en caso de usar variables puede ser peligroso).

Obtener el espacio usado en un directorio ejecutando varios


comandos en una línea.
- name: Ejecutar un comando directamente
hosts: servidor
tasks:
- name: Ejecutar
raw: df -hT | grep "/backups"
register: df_backups
- debug: var=df_backups.stdout

MÓDULO SCRIPT
Argumentos obligatorios
script El script a transferir y a ejecutar en el nodo.

© Alfaomega-RC Libros 127


ANSIBLE

Argumentos opcionales (Negrita indica el valor por defecto)


Argumentos Opciones Descripción
chdir Cambia a este directorio antes de
ejecutar el script.
creates Fichero que cuando existe la tarea no se
ejecutará.
decrypt yes Indica si automáticamente se descifra el
no contenido del fichero usando Vault.
removes Fichero que cuando NO existe la tarea NO
se ejecutará.

En el siguiente ejemplo se copia un script de ejemplo al nodo administrado y se


ejecuta, primero cambiándose al directorio /etc/.
Contenido del script ejemplo.sh.
#!/bin/sh
uname -a
free -m
df -hT
cat resolv.conf
Contenido del playbook que transfiere y ejecuta el script
anterior.
- name: Transferir y ejecutar script
hosts: servidor
tasks:
- script: ejemplo.sh
args:
chdir: /etc/
register: salida_ejemplo
- debug: var=salida_ejemplo.stdout_lines

MÓDULO SHELL
En Windows se utiliza el módulo win_shell
Argumentos obligatorios
comando El comando a ejecutar en el nodo administrado.
Argumentos opcionales
chdir Cambia a este directorio antes de ejecutar el
comando.

128 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

creates Fichero que cuando existe la tarea no se


ejecutará.
executable Ruta absoluta de la shell a utilizar para
ejecutar el comando.
removes Fichero que cuando NO existe la tarea NO se
ejecutará.
stdin Establece la entrada por defecto del comando
directamente usando este valor.

En el siguiente ejemplo listamos las variables de entorno dentro de una shell.

Contenido del playbook.


- name: Ejecutar comandos dentro de la shell
hosts: servidor
tasks:
- shell: env
register: variables_entorno
- debug: var=variables_entorno.stdout_lines
Salida al ejecutar el playbook.
TASK [debug] ***************
ok: [servidor] => {
"variables_entorno.stdout_lines": [
"XDG_SESSION_ID=2",
"SHELL=/bin/bash",
"TERM=xterm-256color",
"SSH_CLIENT=95.91.246.199 54512 22",
"SWIFT_TEST_CONFIG_FILE=/etc/swift/test.conf",
"SSH_TTY=/dev/pts/1",
"USER=root",
"MAIL=/var/mail/root",
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbi
n:/bin:/root/bin", "_=/usr/bin/env",
"PWD=/tmp",
"LANG=en_GB.UTF-8",
"SHLVL=4",
"HOME=/root",
"LANGUAGE=en_GB:en",
"LOGNAME=root",
"SSH_CONNECTION=95.91.246.199 54512 91.121.79.141 22",
"LESSOPEN=| /usr/bin/lesspipe %s",
"XDG_RUNTIME_DIR=/run/user/0",
"DISPLAY=cloud.oforte.net:11.0",

© Alfaomega-RC Libros 129


ANSIBLE

"LESSCLOSE=/usr/bin/lesspipe %s %s"
]
}

MÓDULO TELNET
Argumentos obligatorios
command=comando El comando a ejecutar en el nodo
administrado.
Argumentos opcionales
host El servidor en el cual se ejecutará el comando.
password La contraseña para el login.
pause Segundos de pausa entre cada comando realizado.
port Puerto remoto a utilizar.
prompts Lista de prompts esperados antes de ejecutar el
siguiente comando.
timeout Tiempo de espera para operaciones remotas.
user El usuario utilizado para conectarse.

En los siguientes ejemplos nos conectamos a un dispositivo por telnet ya que


no soporta acceso por ssh.

Conexión a router CISCO para comprobar versión.


- name: Conectarse a un servidor telnet y ejecutar comandos
hosts: router
gather_facts: False
tasks:
- name: ejecutar comandos en el switch
telnet:
host: 10.0.0.20
user: cisco
password: cisco
login_prompt: "Username: "
prompts:
- "[>|#]"
command:
- terminal length 0
- show version
register: obtener_version
- debug: var=obtener_version

130 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

MÓDULOS UTILIDADES
Estos módulos son uzilizados para realizar distintas acciones dentro de Ansible.

meta Ejecuta acciones internas de Ansible.


Asegura que una o varias expresiones sean
assert correctas.
async_status Comprueba el estado de una tarea asíncrona.
Falla la ejecución con un mensaje
fail personalizado.
pause Pausa la ejecución de un playbook.
set_fact Establece un fact de un servidor.
set_stats Establece estadísticas de la ejecución actual.
Espera por una condición antes de continuar
wait_for con la ejecución.
wait_for_conn Espera hasta que el sistema remoto sea
ection alcanzable/utilizable.

MÓDULO META

Argumentos obligatorios
tarea flush_handlers Ejecuta las tareas de handlers
pendientes sin tener que esperar
al final del Play.
refresh_inventory Fuerza la relectura del
inventario, en este caso es volver
a ejecutar el script del
inventario dinámico.
clear_facts Limpia los facts de los nodos
administrados.
clear_host_errors Elimina el estado fallido de los
nodos administrados.
end_play Causa que el Play termine sin
nodos fallidos.
reset_connection Interrumpe una conexión
persistente.

© Alfaomega-RC Libros 131


ANSIBLE

En los siguientes ejemplos se muestran distintas tareas útiles al trabajar con


handlers e inventarios.

Forzar la ejecución de los handlers en un momento


específico sin esperar al final de la ejecución.
- name: utilizar flush_handlers
hosts: servidor
tasks:
- name: Configurar ports.conf
copy: src=ports.conf dest=/etc/apache2/ports.conf
notify: restart_httpd
- name: Configurar apache2.conf
copy: src=apache2.conf dest=/etc/apache2/apache2.conf
notify: restart_httpd
- name: Reiniciar httpd si es necesario en este punto y no al final
meta: flush_handlers
- name: Copiar index.html
template: src=index.html.j2 dest=/var/www/index.html
handlers:
- name: restart_httpd
service: name=apache2 state=restarted

Resultado de las tareas al ejecutar el playbook anterior.


PLAY [utilizar flush_handlers] ************
TASK [Gathering Facts] *******************
ok: [servidor]
TASK [Configurar ports.conf] **************
changed: [servidor]
TASK [Configurar apache2.conf] ************
changed: [servidor]
RUNNING HANDLER [restart_httpd] ***********
changed: [servidor]
TASK [Copiar index.html] *****************
changed: [servidor]

PLAY RECAP ***************


servidor : ok=5 changed=4 unreachable=0 failed=0
El siguiente playbook vuelve a leer el inventario dinámico
después de crear una VM.
- name: Crear una VM en openstack
hosts: all
gather_facts: False
tasks:

132 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

- name: Es mejor usar os_server, pero es un ejemplo


command: /sbin/create_vm.sh os.oforte.net debian01 oforte_key
delegate_to: localhost
- name: Refrescar inventario
meta: refresh_inventory

MÓDULO ASSERT

Argumentos obligatorios
that Listado de condiciones a comprobar
Argumentos opcionales (Negrita indica el valor por defecto)
msg Mensaje a utilizar cuando la condición no se cumple.

En el siguiente ejemplo creamos un assert para comprobar que la versión a


instalar está comprendida entre dos valores.

Contenido del playbook que comprueba que la versión a


instalar es correcta.
- name: Ejemplo de uso de assert
hosts: servidor
tasks:
- assert:
that:
- "install_version|float >= 1.0"
- "install_version|float <= 2.0"
msg:
"La versión a instalar debe estar entre 1.0 y 2.0"
Salida del playbook al proporcionar una versión correcta.
PLAY [Ejemplo de uso de assert] ************
TASK [Gathering Facts] *****
ok: [servidor]
TASK [assert] **************
ok: [servidor] => {
"changed": false,
"failed": false,
"msg": "All assertions passed"
}

PLAY RECAP ****************


servidor: ok=1 changed=0 unreachable=0 failed=1

© Alfaomega-RC Libros 133


ANSIBLE

Salida del playbook al proporcionar una versión fuera del


rango permitido.
PLAY [Ejemplo de uso de assert] ***********
TASK [assert] *************
fatal: [servidor]: FAILED! => {
"assertion": "install_version|float <= 2.0",
"changed": false,
"evaluated_to": false,
"failed": true,
"msg": "La version a instalar debe estar entre 1.0 y 2.0"
}
to retry, use: --limit @/tmp/assert.retry

PLAY RECAP ****************


servidor: ok=1 changed=0 unreachable=0 failed=1

MÓDULO FAIL

Argumentos opcionales
msg Mensaje a utilizar cuando la condición se cumple. Si
no se especifica se mostrará un mensaje genérico.

Ejemplo de marcar fallido una ejecución según una condición:

Contenido del playbook que comprueba si la distribución es


CentOS, sino fallará.
- name: Fallar si la distribución no es CentOS
hosts: servidor
tasks:
- fail:
msg: "Lo siento, este playbook solo funciona en CentOS"
when: ansible_distribution != "CentOS"

MÓDULO PAUSE

Argumentos opcionales (Negrita indica el valor por defecto)


minutes Pausa el playbook los minutos especificados.
seconds Pausa el playbook los segundos especificados.
prompt Mensaje opcional a mostrar cuando se pausa la
ejecución.

134 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

En el siguiente ejemplo esperamos unos segundos después de reiniciar un


servicio.

Contenido del playbook.


- name: Reiniciar apache2 y esperar unos segundos después
hosts: servidor
tasks:
- name: Reiniciar apache2
service: name=apache2 state=restarted
- name: Esperar 5 segundos
pause:
seconds: 5
prompt: "Esperar 5 segundos después de reiniciar"

Salida del playbook al ejecutarlo.


PLAY [Reiniciar apache2 y esperar unos segundos después]
***
TASK [Gathering Facts] *****
ok: [servidor]
TASK [Reiniciar apache2] *******************
changed: [servidor]
TASK [Esperar 5 segundos] ******************
Pausing for 5 seconds
(ctrl+C then 'C' = continue early, ctrl+C then 'A' = abort)
ok: [servidor]

PLAY RECAP ****************


servidor: ok=3 changed=1 unreachable=0 failed=0

MÓDULO SET_FACT

Argumentos obligatorios
diccionario Diccionario con clave/valor para definir los
facts del servidor que deseamos.
Argumentos opcionales (Negrita indica el valor por defecto)
cacheable Indica si este fact debe añadirse al fact cache.

En el siguiente ejemplo creamos dos nuevas variables basadas en los valores


obtenidos del servidor.

© Alfaomega-RC Libros 135


ANSIBLE

Contenido del playbook que define dos variables:


memoria_libre_porcentaje y memoria_usada_porcentaje.
- name: Establecer unas variables de servidor
hosts: servidor
tasks:
- name: Definir variables de memoria
set_fact:
memoria_libre_porcentaje: "{{
((ansible_memfree_mb*100)/ansible_memtotal_mb)|int }} %"
memoria_usada_porcentaje: "{{ 100-
((ansible_memfree_mb*100)/ansible_memtotal_mb)|int }} %"
- name: Mostrar memoria libre
debug: var=memoria_libre_porcentaje
- name: Mostrar memoria usada
debug: var=memoria_usada_porcentaje
Ejemplo al ejecutar el anterior playbook.
PLAY [Establecer unas variables de servidor] *************
TASK [Gathering Facts] *****
ok: [servidor]
TASK [Definir variables de memoria] ********
ok: [servidor]
TASK [Mostrar memoria libre] ***************
ok: [servidor] => {
"memoria_libre_porcentaje": "1 %"
}
TASK [Mostrar memoria usada] ***************
ok: [servidor] => {
"memoria_usada_porcentaje": "99 %"
}

PLAY RECAP ***************


servidor: ok=4 changed=0 unreachable=0 failed=0

MÓDULO SET_STATS

Para mostrar las estadísticas la opción "show_custom_stats" en el fichero de


configuración ansible.cfg debe estar habilitada. Es posible utilizar la variable de
entorno ANSIBLE_SHOW_CUSTOM_STATS para activarlo.

Argumentos obligatorios
data Diccionario con clave/valor para definir las
estadísticas.

136 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

Argumentos opcionales (Negrita indica el valor por defecto)


aggregate Indica si se debe agregar los valores en la existe
estadística o debe ser reemplazada.
per_host Indica si las estadísticas son por nodo o para
todos los nodos.

En el siguiente ejemplo establecemos las variables que veíamos en set_fact


pero como estadísticas.

Contenido del playbook que establece las estadísticas.


- name: Establecer unas variables de servidor
hosts: servidor
tasks:
- name: Definir variables de memoria
set_stats:
data:
memoria_libre: "{{
((ansible_memfree_mb*100)/ansible_memtotal_mb)|int }} %"
memoria_usada: "{{ 100-
((ansible_memfree_mb*100)/ansible_memtotal_mb)|int }} %"
per_host: True
Resultado al ejecutarlo.
# ANSIBLE_SHOW_CUSTOM_STATS=true ansible-playbook set_stats.yml
PLAY [Establecer unas variables de servidor] ******
TASK [Gathering Facts] ***********
ok: [ servidor]
TASK [Definir variables de memoria] **************
ok: [ servidor]

PLAY RECAP ***


servidor: ok=2 changed=0 unreachable=0 failed=0

CUSTOM STATS: ********************


servidor: { "memoria_libre": "1 %", "memoria_usada": "99 %"}

MÓDULO WAIT_FOR

Argumentos opcionales (Negrita indica el valor por defecto)


Argumentos Opciones Descripción
active_connection_states Listado de estados de

© Alfaomega-RC Libros 137


ANSIBLE

conexiones TCP que son


contados como conexiones
activas. Por
defecto:[u'ESTABLISHED',
u'FIN_WAIT1', u'FIN_WAIT2',
u'SYN_RECV', u'SYN_SENT',
u'TIME_WAIT']
connect_timeout Número máximo de segundos a
esperar para la realización de
la conexión antes de cerrar y
volver a intentarlo. Por
defecto 5.
delay Número de segundos a esperar
antes del primer intento.
exclude_hosts Lista de hosts o IPs a ignorar
cuando se observa por
conexiones TCP activas para
desconectarlas.
host Un hostname o IP por el que
esperar.
msg Sobrescribe el mensaje de
error cuando se cumplen las
condiciones.
path Ruta a un fichero del sistema
de fichero que debe existir
antes de continuar.
port Número de puerto a consultar.
search_regex Expresión regular a ser usada
para comprobar un fichero o
una conexión.
sleep Número de segundos a esperar
durante comprobaciones.
state absent Cuando se comprueba un puerto,
drained started asegura que el puerto
present está abierto, stopped
started comprobará que está cerrado,
stopped drained comprobará por
conexiones activas.Cuando se
comprueba por un fichero o se
busca una cadena de texto,
present o started asegurará

138 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

que el fichero o la cadena


está presente antes de
continuar, absent comprobará
que el fichero no existe o
esté eliminado.
timeout Número máximo de segundos a
esperar. Por defecto 300.

En los siguientes ejemplos se realizan tareas comunes después de instalar


software o realizar tareas administrativas en los nodos administrados.

Contenido del playbook para instalar apache2 y esperar que


el puerto 80 esté disponible.
- name: Instalar apache2 y esperar que se esté ejecutando
hosts: servidor
tasks:
- name: Instalar apache2
apt:
name: apache2
state: latest
- name: Arrancar el servicio
service:
name: apache2
state: started
enabled: true
- name: Esperar 60 segundos a que el puerto 80 esté
disponible
wait_for:
port: 80
sleep: 6
timeout: 10
En el siguiente ejemplo se reinicia el servicio apache2 y
se asegura que el fichero PID existe.
- name: Reiniciar apache2 y esperar que se esté ejecutando
hosts: servidor
tasks:
- name: Reiniciar el servicio
service:
name: apache2
state: restarted
enabled: true
- name: Esperar 60 segundos a que el fichero PID exista

© Alfaomega-RC Libros 139


ANSIBLE

wait_for:
path: /var/run/apache2/apache2.pid
sleep: 6
timeout: 10
El siguiente playbook actualiza el sistema, y si así fuese
reiniciará el sistema y esperará a que esté disponible el
puerto 22.
- name: Reiniciar el sistema y esperar al reinicio
hosts: redhat
become: True
tasks:
- name: Actualizar el sistema
yum:
name: "*"
state: latest
register: actualizado
- name: Reiniciar el sistema
shell: sleep 5 && shutdown -r now "Ansible reboot"
ignore_errors: True
async: 1
poll: 0
when: actualizado|changed
- name: Esperar a que el puerto 22 esté disponible
wait_for:
port: 22
host: "{{ inventory_hostname }}"
state: started
sleep: 15
timeout: 60
delegate_to: localhost
become: false
when: actualizado|changed

MÓDULO WAIT_FOR_CONNECTION

Argumentos opcionales (Negrita indica el valor por defecto)


connect_timeout Número máximo de segundos a esperar para la
realización de la conexión antes de cerrar y
volver a intentarlo. Por defecto 5.
delay Número de segundos a esperar antes del
primer intento.

140 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

sleep Número de segundos a esperar durante


comprobaciones.
timeout Número máximo de segundos a esperar. Por
defecto 300.

El último ejemplo que se muestra para el módulo wait_for espera a que el


servidor se reinicie y el puerto 22 (o el indicado) esté disponible. Esa acción se
puede realizar con este módulo de una forma más simple al requerir menos
opciones y no es necesaria la opción delegate_to.

Contenido del playbook utilizando wait_for_connection.


- name: Reiniciar el sistema y esperar al reinicio
hosts: redhat
become: True
tasks:
- name: Actualizar el sistema
yum:
name: "*"
state: latest
register: actualizado
- name: Reiniciar el sistema
shell: sleep 5 && shutdown -r now "Ansible reboot"
ignore_errors: True
async: 1
poll: 0
when: actualizado|changed
- name: Esperar a que el servidor esté disponible
wait_for_connection:
delay: 15
timeout: 60
when: actualizado|changed

MÓDULOS NOTIFICACIONES
Estos módulos son utilizados para usar diferentes proveedores o servicios para
el envío de notificaciones utilizando Ansible.

hipchat Envía notificaciones al servicio popular Hipchat.


irc Envía un mensaje a un canal IRC.
jabber Envía un mensaje a un usuario o canal de Jabber.

© Alfaomega-RC Libros 141


ANSIBLE

mail Envía una notificación por correo electrónico.


pushbullet Envía notificaciones a Pushbullet.
pushover Envía notificaciones utilizando pushover.net
rocketchat Envía notificaciones a Rocket Chat.
slack Envía una notificación a la plataforma Slack.
syslog Envía mensajes a syslog.
telegram Envía la notificación a la plataforma de
mensajería hipchat.

Otros módulos de notificación no tratados en este libro:

bearychat Envía notificaciones a BearyChat


campfire Envía mensajes a campfire.
catapult Envía un sms/mms usando la API de catapult.
cisco_spark Envía un mensaje a un usuario o canal de
Cisco Spark.
flowdock Envía mensaje a flowdock.
grove Envía mensaje a un canal de grove.io.
hall Envía notificación a hall.
mattermost Envía notificaciones por mattermost.
mqtt Publica un mensaje en un asunto de MQTT para
IoT (Internet of the things).
nexmo Envía un SMS usando nexmo.
office_365_con Crea mensajes en Connector Card dentro de un
nector_card grupo de Office 365.
osx_say Notifica a un equipo OSX para que hable.
sendgrid Envía correos electr'onicos utilizando el API
de Send Grid.
twilio Envía mensajes de texto a teléfonos
utilizando Twilio.
typetalk Envía mensajes a typetalk.

142 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

MÓDULO HIPCHAT

Argumentos obligatorios
room=canal ID o nombre de la sala.
token=codigo Código API.
msg=mensaje El cuerpo del mensaje.
Argumentos opcionales (Negrita indica el valor por defecto)
Argumentos Opciones Descripción
from Nombre que aparecerá como usuario
que envió el mensaje. Por defecto:
Ansible
msg_format text Formato del mensaje.
html
notify yes Una notificación será enviada a los
no usuarios de la sala.
validate_certs yes Indica si debe validar los
no certificados SSL.

En el siguiente ejemplo enviamos un mensaje a un canal dentro de Hipchat.

Contenido del playbook.


- name: Enviar notificación a hipchat
hosts: localhost
tasks:
- name: Usando el token enviamos un msg al canal Ansible
hipchat:
api: https://api.hipchat.com/v2
token: "qyckDGUnKLg1beBqirqtedffnVFjDKFUnngMQqGz"
room: Ansible
msg: "La tarea ha finalizado correctamente"
Captura de pantalla de la notificación enviada por Ansible.

© Alfaomega-RC Libros 143


ANSIBLE

MÓDULO IRC

Argumentos obligatorios
channel=canal Nombre del canal. Una de las opciones
channel o nick_to debe ser establecida. Es
posible especificar ambas.
nick_to=usuario Una lista de nicks a enviar mensajes.
msg=mensaje Cuerpo del mensaje.
Argumentos opcionales (Negrita indica el valor por defecto)
Argumentos Opciones Descripción
color none Color para el mensaje.
white
black
blue
green
red
brown
purple
orange
yellow
light_green
teal
light_cyan
light_blue
pink
graylight_gray
key Clave del canal.
nick Nickname del usuario que enviará el
mensaje. Por defecto ansible.
part Indica si el usuario debe ser parte
del canal para enviar el mensaje o
no.
passwd Contraseña del servidor IRC.
port Puerto del servidor IRC.
server Dirección del servidor IRC.
style bold Estilo de texto para el mensaje.
underline
reverse
italic

144 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

timeout TIempo de espera máximo mientras


espera que se conecta al servidor y
se envía al mensaje.
topic Establece el asunto del canal.
use_ssl Indica si debe utilizarse TSL/SSL
al conectarse al servidor.

En el siguiente ejemplo enviamos un mensaje al canal #libroansible de la red


de IRC FreeNode.

Playbook para enviar un mensaje a un canal de IRC.


- name: Enviar mensaje a un canal de IRC
hosts: localhost
gather_facts: False
tasks:
- name: Notificar al canal "#libroansible"
irc:
server: irc.freenode.net
part: true
channel: "#libroansible"
nick: notificador
msg: "La tarea ha finalizado correctamente"
Captura de la notificación.

MÓDULO JABBER

Argumentos obligatorios
msg=mensaje El cuerpo del mensaje.
password=clave La contraseña del usuario con el que
conectarse.
to=usuario/canal ID de usuario o nombre de la sala a donde
enviar el mensaje.
user=usuario
Usuario con el que conectarse.

© Alfaomega-RC Libros 145


ANSIBLE

Argumentos opcionales (Negrita indica el valor por defecto)


encoding Codificación del mensaje.
host Servidor al que conectarse.
port Puerto al que conectarse. Por defecto 5222.

En el siguiente ejemplo utilizamos el servicio de jwchat.org para enviar un


mensaje utilizando el servicio de Jabber.

Contenido del playbook.


- name: Enviar mensaje a un usuario de Jabber
hosts: localhost
gather_facts: False
tasks:
- name: Instalar librería xmpppy necesaria
pip:
name: git+https://github.com/ArchipelProject/xmpppy
state: latest
- name: Notificar al usuario ansible@jwchat.org"
jabber:
user: ansible@jwchat.org
password: libroansible
to: ansible@jwchat.org
msg: "La tarea ha finalizado correctamente"
Mensaje recibido por el propio usuario.

146 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

MÓDULO MAIL

Argumentos obligatorios
subject=asunto El asunto del correo a ser enviado.

Argumentos opcionales (Negrita indica el valor por defecto)


attach Una lista de rutas separadas por
coma de ficheros a adjuntar al
mensaje.
bcc Lista de correos a ser usados como
copia oculta.
body El cuerpo del mensaje a ser enviado.
cc La dirección de correos a ser usada
como copia.
charset El juego de caracteres a ser
utilizado. Por defecto us-ascii
from La dirección de correo del
remitente. Por defecto root
headers Una lista de cabeceras a ser
añadidas al correo.
host El servidor de correo a utilizar.
Por defecto localhost.
password La contraseña si SMTP la requiere.
port El puerto del servidor de correo.
Por defecto 25
secure try Con always solo se enviará el correo
always si está cifrado.Con try intentará
never establecer una conexión segura de
starttls SSL/TLS antes de enviarlo.Con never
no intentará establecer una conexión
segura.Con starttls intentará
cambiar a una conexión segura
después de establecer comunicación.

subtype text El formato a utilizar para el


html contenido.

timeout Establece en segundos el tiempo de


espera. Por defecto 20.

© Alfaomega-RC Libros 147


ANSIBLE

to La dirección de correo a donde


enviar el mensaje. Por defecto root
username El usuario a utilizar si SMTP
requiere autenticación.

En el siguiente ejemplo enviamos la notificación utilizando SMTP.

Contenido del playbook para enviar un correo.


- name: Enviar mensaje por correo
hosts: servidor
gather_facts: False
tasks:
- name: Enviar mensaje a alberto@oforte.net
mail:
host: correo.oforte.net
to: alberto@oforte.net
from: ansible@oforte.net
subject: "La tarea ha finalizado correctamente"
body: "El playbook ejecutando en {{
inventory_hostname }} ha terminado."
Correo recibido.

MÓDULO PUSHBULLET
Argumentos obligatorios
api_key=codigo Código API.
title=titulo Título de la notificación.
Argumentos opcionales (Negrita indica el valor por defecto)
Argumentos Opcio Descripción
nes
body Cuerpo del mensaje de la notificación.
channel El canal a donde se enviará el mensaje.

148 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

device El nombre del dispositivo al que se


desea enviar el mensaje.
push_type note Tipo de notificación a enviar.
link

En el siguiente ejemplo enviamos la notificación al navegador con la extensión


de pushbullet instalada.

Playbook que instala la librería necesaria y envía una


notificación.
- name: Enviar notificación usando pushbullet
hosts: servidor
gather_facts: False
tasks:
- name: Instalar librería necesaria para pushbullet
pip:
name: pushbullet.py
state: present
- name: Notificar al navegador
pushbullet:
api_key: "o.9lJ4Ts23vrI4iqPWzIwe2rnpKL7dZuks"
device: "Chrome"
title: "La tarea ha finalizado correctamente"
Captura de pantalla de la notificación.

© Alfaomega-RC Libros 149


ANSIBLE

MÓDULO PUSHOVER

Argumentos obligatorios
app_token=codigo Código de la aplicación para identificar la
aplicación pushover.
user_key=codigo Clave del usuario a ser utilizada.
msg=mensaje El mensaje a ser enviado.
Argumentos opcionales
pri Prioridad del mensaje.

Ejemplo de notificar a un teléfono usando la plataforma pushover.net:

Contenido del playbook para notificar a un iPhone.


- name: Enviar notificación usando pushover
hosts: localhost
gather_facts: False
tasks:
- name: Notificar al iPhone usando pushover
pushover:
app_token: "ausbrqw1eva55j9ivwku99f1eziimq"
user_key: "uok519gnc3fuv6xfwy7zx8473yan59"
msg: "La tarea ha finalizado correctamente"
Notificación mostrada en el teléfono.

MÓDULO ROCKETCHAT

Argumentos obligatorios
domain=dominio El dominio de tu entorno sin protocolo.
token=codigo Código para Rocket Chat Incoming Webhook.

150 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

Argumentos opcionales
Argumentos Opciones Descripción
attachments Lista de adjuntos.
channel Canal a donde enviar el mensaje.
color normal Permite al texto utilizar colores.
good
warning

icon_emoji Emoticono para el mensaje enviado.


icon_url Dirección URL del icono del usuario
que lo envía.
link_names 10 Automáticamente crea enlaces para
canales y usuarios en los mensajes.
msg Mensaje a ser enviado.
protocol https Especifica el protocolo a ser
http utilizado.
username Usuario que enviará el mensaje. Por
defecto Ansible
validate_certs yes Indica si comprueba el certificado
no SSL.

En el siguiente ejemplo se envía un mensaje a un canal de RocketChat.

Contenido del playbook utilizando un bot de RocketChat.

- name: Enviar notificación a canal de RocketChat


hosts: localhost
gather_facts: False
tasks:
- name: Notificar al canal "#ansible"
rocketchat:
token: "z2SzXEZeRppLhH8nj/mxKbxKZ6CDDp23tkBWr7gmdg3K"
domain: chat.oforte.net:3000
protocol: http
channel: "#ansible"
msg: "La tarea ha finalizado correctamente"

© Alfaomega-RC Libros 151


ANSIBLE

Captura de pantalla del canal #ansible en RocketChat.

MÓDULO SLACK

Argumentos obligatorios
token=código Código de integración Slack.
Argumentos opcionales (Negrita indica el valor por defecto)
attachments Lista de adjuntos.
channel Canal a enviar el mensaje.
color normal Permite que el texto use colores.
good
warning
danger
domain Dominio o subdominio del entorno sin
protocolo.
icon_emoji Emoticono del remitente del mensaje.
icon_url Icono del remitente.
link_names Automáticamente crea enlaces de
canales y usuarios.
msg Mensaje a enviar.
parse none Configura el parseador del mensaje.
full
username El remitente del mensaje. Por defecto
Ansible
validate_certs yes Indica si se debe comprobar el
no certificado SSL de la web.

152 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

En el siguiente ejemplo se envía un mensaje al canal #ansible dentro del


espacio de trabajo oforte.slack.com, el código API está ligado a esos elementos.

Código del playbook para enviar una notificación al canal.


- name: Enviar notificación a canal de Slack
hosts: localhost
gather_facts: False
tasks:
- name: Notificar al canal "#ansible"
slack:
token: "T4SBF8B62/B9SFC3YMC/m12LGs374By5QPDEIo6ZqBFH"
msg: "La tarea ha finalizado correctamente"
Mensaje recibido en Slack.

MÓDULO SYSLOGGER

Argumentos obligatorios
msg=mensaje Mensaje a enviar al syslog.
Argumentos opcionales (Negrita indica el valor por defecto)
Argumentos Opciones Descripción
facility kern Establece el facility.
user
mail
daemon
auth
lpr

© Alfaomega-RC Libros 153


ANSIBLE

news
uucp
cron
syslog
local0..local7
log_pid no Muestra el id del proceso.
yes
priority emerg Establece la prioridad del
alert mensaje.
crit
err
warning
notice
info
debug

En el siguiente ejemplo se envía un mensaje al syslog.

Los mensajes a syslog con facility news y prioridad notice


van a /var/log/news/news.notice.
- name: Enviar notificación al syslog
hosts: localhost
tasks:
- name: Notificar a syslog como news.notice
syslogger:
facility: news
priority: notice
msg: "La tarea ha finalizado correctamente"
Comprobar fichero /var/log/news/news.notice.
# cat /var/log/news/news.notice
Mar 17 17:49:13 cloud ansible_syslogger: La tarea ha
finalizado correctamente

MÓDULO TELEGRAM

Argumentos obligatorios
chat_id Identificador del usuario o del grupo de
Telegram.
msg El mensaje que se desea enviar.
token Código identificando el bot de Telegram.

154 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

Argumentos opcionales (Negrita indica el valor por defecto)


Argumentos Opciones Descripción
msg_format plain Formato del mensaje.
markdown
html

En el siguiente ejemplo se utiliza el bot "LibroAnsibleBot" para enviar un


mensaje al canal "LibroAnsible".
Contenido del playbook utilizando el token del bot y el id
del canal.

- name: Enviar notificación a usuario con Telegram


hosts: localhost
gather_facts: False
tasks:
- name: Notificar usando un telegram bot
telegram:
token: "555517286:ABGvwheGEx4Wuin48G2w52qwYfKZ-hjnc"
chat_id: "-1001252017650"
msg: "La tarea ha finalizado correctamente"

Captura de pantalla del canal.

© Alfaomega-RC Libros 155


ANSIBLE

MÓDULOS BASE DE DATOS


Estos módulos son utilizados para gestionar diferentes gestores de bases de
datos. En negrita se indican los módulos que se detallarán en profundidad.

Módulos para gestionar el gestor de datos MySQL.


Añade o elimina base de datos MySQL de un
mysql_db nodo remoto.
mysql_replication Administra la replicación de MySQL.
Añade o elimina un usuario de una base de
mysql_user datos MySQL.
mysql_variables Gestiona variables globales de MySQL.
Módulos para gestionar el gestor de datos PostgreSQL.
Añade o elimina base de datos PostgreSQL
postgresql_db de un nodo remoto.
Añade o elimina extensiones a una base de
postgresql_ext datos PostgreSQL.
Añade, elimina o cambia lenguajes
procedurales en una base de datos
postgresql_lang PostgreSQL.
Asigna o revoca privilegios a objetos de
postgresql_privs base de datos PostgreSQL.
Añade o elimina esquemas PostgreSQL en un
postgresql_schema nodo remoto.
Añade o elimina usuarios (roles) de una
postgresql_user base de datos PostgreSQL.
Módulos para gestionar el gestor de datos MongoDB.
Cambia parámetros administrativos en un
mongodb_parameter servidor de MongoDB.
Añade o elimina un usuario de una base de
mongodb_user datos MongoDB.
Módulos variados.
elasticsearch_plugin Administra plugins de Elasticsearch.
kibana_plugin Administra plugins de Kibana.
Varios comandos de redis, slave y
redis flush.

156 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

Este módulo gestiona algunas


riak operaciones comunes de Riak.

Existen módulos también para gestionar los gestores de base de datos


InfluxDB, Vertica (HPE) y ProxySQL, los cuales no son tratados en este libro.

MÓDULO MYSQL_DB

Argumentos obligatorios
name=nombre Nombre de la base de datos a añadir o
eliminar.
Argumentos opcionales (Negrita indica el valor por defecto)
collation El modo de collation.
config_file Especifica un fichero de
configuración a utilizar.
connect_timeout Tiempo máximo de espera de
conexión al servidor MySQL. Por
defecto 30.
encoding Codificación a utilizar, por
ejemplo utf8.
login_host Servidor a conectarse. Por
defecto localhost.
login_password La contraseña para autenticarse.
login_port Puerto del servidor MySQL.
login_unix_socket La ruta a un socket para
conexiones locales.

login_user El usuario para autenticarse.

quick Opción usada para la copia de


seguridad de tablas largas.

single_transaction Ejecuta la copia de seguridad en


una transacción única.

state present El estado de la base de datos.


absent
dump
import

© Alfaomega-RC Libros 157


ANSIBLE

target Ubicación en el nodo remoto donde


hacer la copia de seguridad o
fichero a importar.

En los siguientes ejemplos se crea una base de datos y se hace un backup de


todas las bases de datos.
Instalar librería necesaria para utilizar los módulos de
MySQL y crear bbdd llamada ansible.
- name: Crear una base de datos
hosts: servidor
tasks:
- name: Instalar librería PyMysqlDB
pip:
name: PyMysqlDB
state: latest
- name: Crear bbdd ansible
mysql_db:
name: ansible
login_user: ansible
login_password: libroansible
state: present
Hacer copia de seguridad de todas las bases de datos.
- name: Crear una base de datos
hosts: servidor
tasks:
- name: Instalar librería python-mysql
pip:
name: PyMysqlDB
state: latest
- name: Hacer copia de seguridad de todas las bbdds
mysql_db:
name: all
login_user: ansible
login_password: libroansible
state: dump
target: /var/backups/{{ ansible_hostname }}.sql

MÓDULO MYSQL_USER

Argumentos obligatorios
name=nombre Nombre del usuario (rol) a añadir o
borrar.

158 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

Argumentos opcionales (Negrita indica el valor por defecto)


append_privs no Añade los privilegios
yes indicados en vez de
sobrescribir los existentes.
check_implicit_admi no Comprueba si MySQL permite
n yes autenticar como usuario/sin
contraseña antes de usar las
credenciales.
config_file Especifica un fichero de
configuración a utilizar.
connect_timeout Tiempo máximo de espera de
conexión al servidor MySQL.
Por defecto 30.
encrypted no Indica que el campo contraseña
yes es un has de tipo
mysql_native_password
host La parte de servidor del
usuario MySQL. Por defecto
localhost.
host_all no Sobrescribe la opción
yes servidor, haciendo que Ansible
cambie todos los nombres de
servidores para el usuario
dado.
login_host Servidor a conectarse. Por
defecto localhost.
login_password La contraseña para
autenticarse.

login_port Puerto del servidor MySQL.


login_unix_socket La ruta a un socket para
conexiones locales.

login_user El usuario para autenticarse.


password Establece la contraseña del
usuario.

priv Privilegios MySQL en format:


bbdd.tabla:prv1,priv2

© Alfaomega-RC Libros 159


ANSIBLE

sql_log_bin yes Si los registros binarios


no deben ser habilitados o
deshabilitados para la
conexión.
state present Si el usuario debe existir o
absent no.
update_password always Permite actualizar las
on_create contraseñas si son distintas.

En el siguiente ejemplo creamos un usuario y le establecemos los permisos


(GRANT) a dos bases de datos distintas.
Contenido del playbook que crea el usuario y establece dos
permisos a dos bbdds.
- name: Crear usuario y dar permiso
hosts: servidor
tasks:
- name: Instalar librería python-mysql
pip:
name: PyMysqlDB
state: latest
- name: Crear el usuario "libroansible" y darle permiso
mysql_user:
login_user: ansible
login_password: libroansible
name: libroansible
password: nuevousuario123
priv: "ansible.*:ALL/oforte.*:SELECT"
Mostrar los permisos del nuevo usuario (libroansible).
mysql> show grants for 'libroansible'@'localhost';
+-----------------------------------------------------------------
----------------------------------------------------+
| Grants for libroansible@localhost |
+-----------------------------------------------------------------
----------------------------------------------------+
| GRANT USAGE ON *.* TO 'libroansible'@'localhost' IDENTIFIED BY
PASSWORD '*C8B9485A15880257B9B1691796B349D597015F97' |
| GRANT SELECT ON `oforte`.* TO 'libroansible'@'localhost' |
| GRANT ALL PRIVILEGES ON `ansible`.* TO
'libroansible'@'localhost' |
+-----------------------------------------------------------------
----------------------------------------------------+
3 rows in set (0.00 sec)

160 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

ARGUMENTOS POSTGRESQL

Los módulos de PostgresQL tienen estos argumentos opcionales en común:

login_host Servidor a conectarse. Por defecto


localhost.
login_password La contraseña para autenticarse.
login_unix_socket La ruta a un socket para conexiones
locales.
login_user El usuario para autenticarse. Por
defecto postgres.
port Puerto del servidor a conectarse.
ssl_mode prefer
disable
allow Determina si utilizar una conexión
require segura SSL TCP/IP.
verify-ca
verify-full

MÓDULO POSTGRESQL_DB

Argumentos obligatorios
name=nombre Nombre de la base de datos a añadir/eliminar.
Argumentos opcionales (Negrita indica el valor por defecto)
encoding Codificación a utilizar.
lc_collate Collation (LC_COLLATE) a usar.
lc_ctype Clasificación de caracteres
(LC_CTYPE)a usar.
owner Nombre del rol a establecer como
dueño de la base de datos.
state present Estado de la base de datos.
absent
dump
restore
target Ubicación donde realizar la copia de
seguridad o de donde restaurar.
target_opts Argumentos extra para pg_dump o
pg_restore.

© Alfaomega-RC Libros 161


ANSIBLE

template Plantilla a ser usada para crear la


base de datos.

En los siguientes ejemplos se crea una base de datos y se hace un backup de


todas las bases de datos.
Contenido del playbook, se cambia al usuario "postgres" en
el sistema para crear la bbdd.
- name: Crear una base de datos
hosts: servidor
tasks:
- name: Instalar librería psycopg2
pip:
name: psycopg2
state: latest
- name: Crear bbdd ansible
become: True
become_user: postgres
postgresql_db:
name: ansible
state: present
Playbook para realizar backup de las base de datos
especificadas.
- name: Crear una base de datos
hosts: servidor
tasks:
- name: Instalar librería psycopg2
pip:
name: psycopg2
state: latest
- name: Crear directorio para backups de PostgreSQL
file:
path: /var/backups/postgresql/
state: directory
owner: postgres
group: postgres
mode: 0770
- name: Hacer copia de seguridad de las bbdds indicadas
become: True
become_user: postgres
postgresql_db:
name: "{{ item }}"
state: dump
target: /backups/{{ansible_hostname}}_{{ item }}.sql

162 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

with_items:
- ansible
- oforte

MÓDULO POSTGRESQL_USER

Argumentos obligatorios
name=nombre Nombre del usuario (rol) a añadir o borrar.
Argumentos opcionales (Negrita indica el valor por defecto)
conn_limit Especifica el límite de
conexiones del usuario.
db Nombre de la base de datos a dar
permiso.
encrypted Si la contraseña es almacenada
cifrada.
expires Establece la expiración de la
contraseña del usuario.
fail_on_user yes Si se habilita esta opción,
no fallará si el usuario no puede
ser eliminado. De otra forma se
registrará un mensaje y
continuará.
name Nombre del usuario (rol) a
añadir o borrar.
no_password_ no Si se habilita, no inspecciona
changes yes la base de datos por cambios de
contraseña.
password Establece la contraseña del
usuario.
priv Privilegios PostgreSQL en
formato: tabla:prv1,priv2
role_attr_flags [NO]SUPERUSER Atributos de rol PostGRESQL en
[NO]CREATEROLE formato:
[NO]CREATEUSER CREATEDB,CREATEROLE,SUPERUSER
[NO]CREATEDB
[NO]INHERIT
[NO]LOGIN
[NO]REPLICATION
[NO]BYPASSRLS

© Alfaomega-RC Libros 163


ANSIBLE

state present
El estado del usuario (rol).
absent

En el siguiente ejemplo creamos un usuario y se le asigna permisos a una base


de datos creada anteriormente con postgresql_db.

Crear usuario y dar permiso en la base de datos.


- name: Crear usuario y dar permiso
hosts: servidor
tasks:
- name: Instalar librería psycopg2
pip:
name: psycopg2
state: latest
- name: Crear el usuario "libroansible" y darle permiso
become_user: postgres
become: True
postgresql_user:
db: ansible
name: libroansible
password: nuevousuario123
priv: "ALL"
Comprobar permisos.
ansible=> \l ansible
List of databases

Name | Owner | Encoding | Collate | Ctype | Access privileges


---------+----------+----------+-------------+-------------+---------------------------

ansible | postgres | UTF8 | en_GB.UTF-8 | en_GB.UTF-8 | =Tc/postgres +


| | | | | postgres=CTc/postgres +

| | | | | libroansible=CTc/postgres

(1 row)

MÓDULO POSTGRESQL_PRIVS

Argumentos obligatorios
database=bdd Nombre de la base de datos a conectarse.
roles=lista Lista separada por coma de los roles
(usuar/grupo) a establecer permisos.

164 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

Argumentos opcionales (Negrita indica el valor por defecto)


grant_option no Si el rol debe ser
yes asociado/revocado de los
grupos/privilegios especificados.
objs Lista separada por comas de objetos
de base de datos a establecer
privilegios.
privs Lista separada por comas de
privilegios a asociar/revocar.
schema Esquema que contiene los objetos de
base de datos.
state present Indica si los privilegios deben ser
absent asociados o revocados.
type table Tipo de objeto de base de datos a
sequence establecer privilegios.
function
database
schema
language
tablespace
group

En el siguiente ejemplo se establecen permisos al usuario anteriormente


creados con postgresql_user a la base de datos importada.

Importar una base de datos y darle permisos.


- name: Crear usuario y dar permiso
hosts: servidor
tasks:
- name: Instalar librería psycopg2-binary
pip:
name: psycopg2-binary
state: latest
- name: Crear base de datos dvds
become_user: postgres
become: True
postgresql_db:
name: dvds
state: present
- name: Restaurar base de datos dvds
become_user: postgres

© Alfaomega-RC Libros 165


ANSIBLE

become: True
postgresql_db:
name: dvds
state: restore
target: /var/lib/postgresql/restore.sql
- name: Dar permisos al usuario "libroansible"
become_user: postgres
become: True
postgresql_privs:
db: postgres
privs: ALL
objs: dvds
type: database
roles: libroansible
Comprobación
postgres=# \l dvds
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
------+----------+----------+-------------+-------------+---------------------------
dvds | postgres | UTF8 | en_GB.UTF-8 | en_GB.UTF-8 | =Tc/postgres +
| | | | | postgres=CTc/postgres +
| | | | | libroansible=CTc/postgres

MÓDULO POSTGRESQL_SCHEMA

Argumentos obligatorios
name=nombre Nombre del esquema a añadir o borrar.
Argumentos opcionales (Negrita indica el valor por defecto)
database Nombre de la base de datos a
conectarse.
owner Nombre del rol a establecer como
dueño del esquema.
state present Estado del esquema.
absent

En el siguiente ejemplo se crea un nuevo esquema llamado "esq_ansible":

Contenido del playbook usando postgresql_schema.


- name: Crear un nuevo esquema
hosts: servidor

166 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

tasks:
- name: Instalar librería psycopg2
pip:
name: psycopg2
state: latest
- name: Crear un nuevo esquema llamado ansible
become: True
become_user: postgres
postgresql_schema:
name: "esq_ansible"
state: present
Comprobación de la creación del esquema.
postgres=# \dn
List of schemas
Name | Owner
-------------+----------
esq_ansible | postgres
public | postgres
(2 rows)

MÓDULO MONGODB_USER

Argumentos obligatorios
name=nombre Nombre del usuario a añadir/borrar.
database=bdd El nombre de la base de datos a donde
añadirlo.
Argumentos opcionales (Negrita indica el valor por defecto)
login_database La base de datos donde las
credenciales se almacenan.
login_host Servidor a conectarse.
login_password La contraseña para
autenticarse.
login_port Puerto del servidor a
conectarse.
login_user El usuario para autenticarse.
password La contraseña a utilizar para
el usuario.
replica_set El conjunto de réplicas a
conectarse.

© Alfaomega-RC Libros 167


ANSIBLE

roles Los roles del usuario de la


base de datos validos pueden
ser uno o varios.
ssl Si utiliza SSL o no.
ssl_cert_reqs CERT_REQUIRED
Especifica si un certificado
CERT_OPTIONAL
es requerido.
CERT_NONE
state present El estado del usuario de base
absent de datos.
update_password always Actualiza siempre las
on_create contraseñas o no.

En el siguiente ejemplo se instala MongoDB y se crea el primer usuario como


administrador.

Contenido del playbook.


- name: Instalar MongoDB y crear usuario
hosts: servidor
tasks:
- name: Instalar MongoDB
apt:
name: mongodb
state: latest
- name: Iniciar MongoDB
service:
name: mongodb
state: started
enabled: true
- name: Crear primer usuario
mongodb_user:
database: admin
user: ansible
password: nuevousuario123
roles: userAdminAnyDatabase
Comprobación de la creación del usuario.
# mongo admin
MongoDB shell version: 2.4.10
connecting to: admin
> show users
{
"_id" : ObjectId("5aaecc09bfc79279b1ef9afd"),

168 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

"pwd" : "2939c1052267427b36b2e5234a69da62",
"user" : "ansible",
"roles" : [
"userAdminAnyDatabase"
]
}

MÓDULOS SISTEMA
Estos módulos son utilizados para gestionar diferentes elementos del sistema
operativo. En negrita se indican los módulos que se detallarán en profundidad.

aix_inittab Administra el inittab en AIX.


aix_lvol Configurar volúmenes lógicos AIX LVM.
Administra programas alternativos para
alternatives comandos comunes.
Programa la ejecución de un comando o
at archivo de script mediante el comando at.
Agrega o elimina una clave autorizada
authorized_key SSH.
awall Administra políticas de un muro.
Gestiona entornos de arranque ZFS en
beadm sistemas FreeBSD / Solaris / illumos.
capabilities Administra capacidades de Linux.
cron Administra las entradas cron.d y crontab.
cronvar Administra variables en crontabs.
crypttab Dispositivos de bloques Linux cifrados.
dconf Modifica y lee la base de datos dconf.
debconf Configura un paquete .deb.
Ejecuta el programa de descubrimiento
facter facter en el sistema remoto.
Crea el sistema de ficheros dentro del
filesystem dispositivo.
Administra puertos / servicios
firewalld arbitrarios con firewalld.
gconftool2 Edita configuraciones de GNOME.

© Alfaomega-RC Libros 169


ANSIBLE

getent Llama a la utilidad getent del sistema.


gluster_volume Administra volúmenes GlusterFS.
group Agrega o elimina grupos.
hostname Administra nombre de host.
Ajusta las configuraciones en los
interfaces_file archivos /etc/network/interfaces.
iptables Modifica los sistemas iptables.
Utiliza keytool para importar / eliminar
java_cert clave de java keystore (cacerts).
kernel_blacklist Módulos del núcleo de la lista negra.
Agrega o elimina un host del archivo
known_hosts ``known_hosts``.
Crea o elimina configuraciones
locale_gen regionales.
lvg Configura grupos de volúmenes LVM.
lvol Configura volúmenes lógicos LVM.
make Ejecuta objetivos en un archivo Makefile.
modprobe Agrega o elimina módulos kernel.
Controla puntos de montaje activos y
mount configurados.
ohai Devuelve datos de inventario de Ohai.
Administra los objetivos iscsi con
open_iscsi abierto.
openwrt_init Administra servicios en OpenWrt.
Lee, escribe y elimina los valores
predeterminados de usuario de Mac OS X de
osx_defaults Ansible.
pam_limits Modifica los límites de PAM de Linux.
pamd Administra módulos PAM.
Configura particiones de dispositivos de
parted bloques.
Intenta conectarse al host, verifica una
python utilizable y devuelve ``pong`` al
ping éxito.
puppet Ejecuta puppet.

170 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

runit Administra servicios runit.


seboolean Alterna SELinux booleanos.
Gestiona las definiciones de mapeo de
sefcontext contexto del archivo SELinux.
Cambia la política y el estado de
selinux SELinux.
Cambia el dominio permisivo en la
selinux_permissive política de SELinux.
Administra definiciones de tipo puerto
seport SELinux.
service Administrar servicios.
setup Recopila datos sobre hosts remotos.
solaris_zone Administra zonas de Solaris.
svc Administra servicios daemontools.
sysctl Administra entradas en sysctl.conf.
systemd Administra servicios.
Configura la configuración de la zona
timezone horaria.
ufw Administra el firewall con UFW.
user Administra cuentas de usuario.

MÓDULO ALTERNATIVES

Argumentos obligatorios
name=nombre Nombre genérico del enlace.
path=ruta Ruta al ejecutable real.
Argumentos opcionales
priority Prioridad de la alternative. Por defecto 50.

En el siguiente ejemplo instalamos Java 8 y actualizamos el enlace de java a la


nueva versión.

Contenido del playbook.


- name: Instalar java 8 y configurar enlace
hosts: servidor

© Alfaomega-RC Libros 171


ANSIBLE

tasks:
- name: Comprobar versión antes de alternatives
command: java -version
register: java_version
- debug: var=java_version.stderr
- apt:
name: openjdk-8-jre
state: latest
- alternatives:
name: java
path: /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java
- name: Comprobar version despues de alternatives
command: java -version
register: java_version
- debug: var=java_version.stderr

Salida del playbook para comprobar la versión antes y


después.

PLAY [Instalar java 8 y configurar enlace] **


TASK [Gathering Facts] **
ok: [servidor]
TASK [Comprobar versión antes de alternatives] **
changed: [servidor]
TASK [debug] **********
ok: [servidor] => {
"java_version.stderr": "java version \"1.7.0_151\"\nOpenJDK
Runtime Environment (IcedTea 2.6.11) (7u151-2.6.11-
2~deb8u1)\nOpenJDK 64-Bit Server VM (build 24.151-b01, mixed mode)"
}
TASK [apt] *************
changed: [servidor]
TASK [alternatives] ****
changed: [servidor]
TASK [Comprobar version despues de alternatives] **
changed: [servidor]
TASK [debug] **********
ok: [servidor] => {
"java_version.stderr": "openjdk version \"1.8.0_131\"\nOpenJDK
Runtime Environment (build 1.8.0_131-8u131-b11-1~bpo8+1-
b11)\nOpenJDK 64-Bit Server VM (build 25.131-b11, mixed mode)"
}

PLAY RECAP **********


servidor : ok=7 changed=4 unreachable=0 failed=0

172 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

MÓDULO AUTHORIZED_KEYS

Argumentos obligatorios
key=clave La clave pública SSH.
user=usuario El usuario remoto a modificar su fichero.
Argumentos opcionales (Negrita indica el valor por defecto)
comment Cambia el comentario de la clave
pública.
exclusive no Si debe borrar todas las claves
yes existentes.
key_options Las opciones para la clave.
manage_dir yes Indica si el módulo debe administrar
no el directorio del fichero.
path Ruta alternativa al fichero.
state present El estado de la clave en el fichero.
absent
validate_certs yes Valida el certificado SSL de la web a
no la que conectarse.

En el siguiente ejemplo se distribuye una clave pública a los nodos remotos


administrados. Utilizamos cat para leer el contenido del fichero pero en el
capítulo avanzado hablaremos sobre los filtros entre los que se encuentra uno
para leer fichero sin tener que ejecutar un comando.

Contenido del playbook.


- name: Copiar clave pública de SSH
hosts: servidor
tasks:
- name: Leer public key del usuario actual
command: cat ~/.ssh/id_rsa.pub
register: clave_publica
changed_when: False
delegate_to: localhost
- name: Copiar clave a un usuario del nodo remoto
authorized_key:
user: alberto
state: present
key: "{{ clave_publica.stdout }}"

© Alfaomega-RC Libros 173


ANSIBLE

MÓDULO CRON

Argumentos opcionales (Negrita indica el valor por defecto)


backup no Indica si realizar copia de seguridad.
yes
cron_file Fichero en vez del cron del usuario.
day Día del mes (1-31, *, */2, etc ). Por
dom defecto "*".
disabled Si el trabajo debe estar deshabilitado.
env no Si debe administrar variables de
yes entorno del trabajo cron.
hour Hora (0-23,*,*/2,etc ). Por defecto
"*".
insertafter Usado para variables de entorno.
insertbefore Usado para variables de entorno.
job El comando a ejecutar o el valor de la
value variable de entorno.
minute Minuto (0-59,*,*/2..). Por defecto "*".
month Mes del año ( 1-12, *, */2, etc ). Por
defecto "*".
name Descripción del trabajo o de la
variable de entorno.
special_time reboot Tiempo especial.
yearly
annually
monthly
weekly
daily
hourly
state present Estado del trabajo o de la variable de
absent entorno.
user El usuario al que el trabajo debe ser
indicado.
weekday Día de la semana (0-6 para Domingo-
dow Sábado, *, etc.). Por defecto "*".

174 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

En el siguiente ejemplo se crea un crontab para realizar copias de seguridad


usando la utilidad rsnapshot, se programan cuatro tareas: cada cuatro horas,
diaria, semanal y mensual.

Contenido del playbook para añadir a cron cuatro tareas de


copia de seguridad.
- name: Programar copia de seguridad usando rsnapshot
hosts: servidor
tasks:
- name: Backup cada cuatro horas
cron:
name: "backup_cada_4_horas"
hour: "*/4"
minute: 0
user: root
job: "/usr/bin/rsnapshot hourly"
cron_file: copiaseguridad
- name: Backup cada día
cron:
name: "backup_diario"
hour: 3
minute: 30
user: root
job: "/usr/bin/rsnapshot daily"
cron_file: copiaseguridad
- name: Backup semanal
cron:
name: "backup_semanal"
hour: 3
minute: 0
weekday: 1
user: root
job: "/usr/bin/rsnapshot weekly"
cron_file: copiaseguridad
- name: Backup mensual
cron:
name: "backup_mensual"
hour: 2
minute: 30
day: 1
user: root
job: "/usr/bin/rsnapshot monthly"
cron_file: copiaseguridad

© Alfaomega-RC Libros 175


ANSIBLE

Fichero generado después de ejecutar el playbook.


# cat /etc/cron.d/copiaseguridad

#Ansible: backup_cada_4_horas
0 */4 * * * root /usr/bin/rsnapshot hourly
#Ansible: backup_diario
30 3 * * * root /usr/bin/rsnapshot daily
#Ansible: backup_semanal
0 3 * * 1 root /usr/bin/rsnapshot weekly
#Ansible: backup_mensual
30 2 1 * * root /usr/bin/rsnapshot monthly

MÓDULO FILESYSTEM

Argumentos obligatorios
dev=dispositivo Dispositivo.
fstype=tipo Tipo de sistema de ficheros.
Argumentos opcionales (Negrita indica el valor por defecto)
force no Forzar la creación del sistema de
yes ficheros aunque ya tenga uno.
opts Lista de opciones a ser pasadas al
comando mkfs.
resizefs no Si debe cambiar el tamaño.
yes

Crear un sistema de ficheros en una partición previamente creada.

Contenido del playbook que instala las utilidades de XFS y


formatea la partición.
- name: Formatear partición sda5 con xfs
hosts: servidor
tasks:
- name: Instalar xfsprogs para poder formatear
apt:
name: xfsprogs
state: present
- name: Formatear partición
filesystem:
dev: /dev/sda5
fstype: xfs

176 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

MÓDULO FIREWALLD

Argumentos obligatorios
state=enabled/disabled Estado de la regla.
Argumentos opcionales (Negrita indica el valor por defecto)
immediate False Aplicar inmediatamente.
True
interface La interfaz a añadir/eliminar a(de
una zona.
masquerade False Establecer enmascarado.
True
permanent False Si debe ser una regla permanente.
True
port Nombre del puerto o rango.
rich_rule Regla rica.
service Nombre del servicio.
source Origen
timeout Tiempo máximo de espera.
zone work Zona a utilizar.
drop
internal
external
trusted
home
dmz
public
block

En los siguientes ejemplos se muestran tareas habituales con FirewallD.

Playbook para permitir conexión a los servicios de HTTP(S).


- name: Permitir HTTP y HTTPS
hosts: servidor
tasks:
- name: Arrancar el servicio de firewallD.
service:
name: firewalld
state: started

© Alfaomega-RC Libros 177


ANSIBLE

enabled: true
- firewalld:
service: "{{ item }}"
permanent: True
state: enabled
notify: reload firewalld
with_items:
- http
- https
handlers:
- name: reload firewalld
command: firewall-cmd --reload

Comprobación del playbook anterior.


# firewall-cmd --list-all
public (active)
target: default
icmp-block-inversion: no
interfaces: eth0
sources:
services: dhcpv6-client http https ssh
ports:
protocols:
masquerade: no
forward-ports:
sourceports:
icmp-blocks:
rich rules:

Crear regla avanzada para permitir conexión a MySQL pero


limitando el número de conexiones y auditando.
- name: Permitir MySQL pero usando reglas avanzadas
hosts: servidor
tasks:
- name: Arrancar el servicio de firewallD
service:
name: firewalld
state: started
enabled: true
- firewalld:
rich_rule: 'rule service name="mysql" audit limit value="1/m" accept'
permanent: true
state: enabled
notify: reload firewalld

178 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

handlers:
- name: reload firewalld
command: firewall-cmd --reload
Comprobación de creación de la regla avanzada
# firewall-cmd --list-all
public (active)
target: default
icmp-block-inversion: no
interfaces: eth0
sources:
services: dhcpv6-client http https ssh
ports:
protocols:
masquerade: no
forward-ports:
sourceports:
icmp-blocks:
rich rules:
rule service name="mysql" audit limit value="1/m" accept
# firewall-cmd --list-rich-rules
rule service name="mysql" audit limit value="1/m" accept

MÓDULO GETENT

Argumentos obligatorios
database=bbdd Base de datos a consultar (passwd, group,
hosts, etc.).
Argumentos opcionales
fail_key Indica si la tarea falla si no se encuentra lo
buscado. Por defecto True.
key Elemento a buscar.
split Carácter a ser utilizado para dividir los
datos, como ':' o ' '.

En el siguiente ejemplo se muestran la consulta y la información obtenida.

Contenido del playbook para obtener y visualizar la


información.
- name: Obtener información de un usuario usando getent
hosts: servidor

© Alfaomega-RC Libros 179


ANSIBLE

tasks:
- name: Obtener info del usuario alberto
getent:
database: passwd
key: alberto
register: info_usuario
- debug: var=info_usuario
TASK [debug] **********
ok: [servidor] => {
"info_usuario": {
"ansible_facts": {
"getent_passwd": {
"alberto": [
"x",
"1000",
"1002",
"",
"/home/alberto",
"/bin/sh"
]
}
},
"changed": false,
"failed": false
}
}

MÓDULO GROUP

Argumentos obligatorios
name=nombre Nombre del grupo a gestionar.
Argumentos opcionales (Negrita indica el valor por defecto)
gid Identificador del grupo.
state present Estado del grupo, si debe existir o
absent no.
system no Indica si el grupo es de sistema.
yes

En el siguiente ejemplo se crea un grupo que será utilizado posteriormente al


crear un usuario (módulo user).

180 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

Contenido del playbook usando los módulos group y getent.


- name: Crear el grupo ansible y ver propiedades
hosts: servidor
tasks:
- name: Crear el grupo
group:
name: ansible
- name: Obtener información
getent:
database: group
key: ansible
register: info_grupo
- debug: var=info_grupo
Resultado de mostrado al ejecutar el playbook.
PLAY [Crear el grupo ansible y ver propiedades] ************
TASK [Gathering Facts] **
ok: [servidor]
TASK [Crear el grupo] ****
changed: [servidor]
TASK [Obtener información] *****************
ok: [servidor]
TASK [debug] **********
ok: [servidor] => {
"info_grupo": {
"ansible_facts": {
"getent_group": {
"ansible": [
"x",
"1003",
""
]
}
},
"changed": false,
"failed": false
}
}

PLAY RECAP **********


servidor: ok=4 changed=1 unreachable=0 failed=0

© Alfaomega-RC Libros 181


ANSIBLE

MÓDULO HOSTNAME

Argumentos obligatorios
name=nombre Nombre del servidor a establecer.

En el siguiente ejemplo se establece el hostname del servidor. Este módulo es


de gran utilidad cuando se despliega máquinas virtuales basadas en una plantilla.
Contenido del playbook.
- name: Establece el hostname del sistema
hosts: servidor
tasks:
- hostname:
name: cloud.oforte.net

MÓDULO IPTABLES

Argumentos opcionales (Negrita indica el valor por defecto)


action append Añadir o insertar la regla.
insert
chain Chain donde trabajar: 'INPUT',
'FORWARD', 'OUTPUT', 'PREROUTING',
'POSTROUTING', 'SECMARK',
'CONNSECMARK'.
comment Comentario de la regla.
ctstate ctstate a establecer: 'INVALID',
'NEW', 'ESTABLISHED', 'RELATED',
'UNTRACKED', 'SNAT', 'DNAT'
destination Especifica la dirección destino.
destination_port Puerto o rango de puertos destino.
flush Limpia la table.
fragment Indica si esta regla refiere a la
segunda o siguientes fragmentos.
goto Especifica si procesando esta regla
debe continuar en un especificado
chain.
icmp_type Tipo de ICMP.
in_interface Nombre de la interfaz donde el
paquete será recibido.

182 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

ip_version ipv4 Protocolo IP.


ipv6
jump Especifica la regla destino.
limit Especifica el limite por Segundo.
limit_burst Especifica el máximo burst anes de
que el límite bloquee.
match Especifica un match a utilizar.
out_interface Nombre de la interfaz por donde el
paquete será enviado.
policy Política para el chain: ACCEPT,
DROP, QUEUE, RETURN.
protocol Protocolo de la regla.
reject_with Especifica el error del rechazo.
set_counters Habilita los contadores de la
regla.
source Origen.
source_port Puerto o rango de puerto origen.
state present Estado de la regla.
absent
table filter Tabla en la que operar.
nat
mangle
raw
security
to_destination Destino a ser usado con DNAT.
to_ports Puertos destino.
to_source Especifica la dirección origen a
usar con SNAT.
uid_owner Especifica el UID o nombre usuario
del dueño de la regla.

En los siguientes ejemplos se muestran tareas comunes realizadas con el


comando iptables.

Playbook para permitir acceso a los puertos 80 y 443.


- name: Permitir HTTP y HTTPS

© Alfaomega-RC Libros 183


ANSIBLE

hosts: servidor
tasks:
- iptables:
action: insert
chain: INPUT
source: 0.0.0.0/0
destination_port: "{{ item }}"
protocol: tcp
jump: ACCEPT
state: present
with_items:
- 80
- 443
Redirigir puerto 80 al servidor 192.168.56.102.
- name: Redirigir el puerto 80 a otro servidor
hosts: servidor
become: True
tasks:
- iptables:
table: nat
chain: PREROUTING
action: insert
in_interface: eth0
protocol: tcp
match: tcp
jump: DNAT
destination_port: 80
to_destination: 192.168.56.102
comment: Redigir tráfico al servidor 192.168.56.102

Comprobación de reglas creadas.


# iptables -L INPUT -v -n
Chain INPUT (policy ACCEPT 226 packets, 11644 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:443
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
# iptables -t nat -L PREROUTING -v -n
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 DNAT tcp -- eth0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 /*
Redigir trafico al servidor 192.168.56.102 */
to:192.168.56.102

184 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

MÓDULO KNOWN_HOSTS

Argumentos obligatorios
name=clave El servidor a añadir o borrar.
host=clave
Argumentos opcionales (Negrita indica el valor por defecto)
hash_host Hash del servidor.
key La clave pública SSH del servidor.
path El fichero known_hosts a editar.
state present Estado de la clave.
absent

En el siguiente ejemplo se añade al fichero known_hosts nuestra clave pública.

Utilizar el comando ssh-keyscan para obtener la clave y


añadir la clave a known_hosts.
- name: Añadir clave al fichero known_hosts
hosts: servidor
tasks:
- name: Leer clave pública del servidor
shell: ssh-keyscan -t rsa cloud.oforte.net | tail -1
register: clave_publica
changed_when: False
delegate_to: localhost
- name: Añadir la clave obtenida anteriormente
known_hosts:
path: /home/alberto/.ssh/known_hosts
state: present
key: "{{ clave_publica.stdout }}"
name: "cloud.oforte.net"

MÓDULO LVG

Argumentos obligatorios
vg=nombre El nombre del grupo de volúmenes.
Argumentos opcionales (Negrita indica el valor por defecto).
force no Fuerza la eliminación.
yes

© Alfaomega-RC Libros 185


ANSIBLE

pesize Tamaño de la extensión física en


megabytes. Por defecto 4
pv_options Opciones adicionales a pasar a pvcreate.
pvs Lista separada de comas de los PVs.
state present Estado del grupo de volúmenes.
absent
vg_options Opciones adicionales a pasar a vgcreate.

En el siguiente ejemplo se crea un grupo de volúmenes llamado "ansible"


utilizando dos discos.

Contenido del playbook.


- name: Crear grupo de volúmenes llamado ansible
hosts: servidor
tasks:
- lvg:
vg: ansible
state: present
pvs:
- /dev/sdc
- /dev/sdd
Comprobación después de ejecutar el playbook.
# vgdisplay -v ansible
[..]
--- Physical volumes
--- PV Name /dev/sdc
PV UUID fKVX3V-pomi-dXVw-kjRS-zk69-MBTD-uK7twj
PV Status allocatable
Total PE / Free PE 1279 / 1279
PV Name /dev/sdd
PV UUID 1YGeF6-jQX5-e7fp-g5Zg-u5jj-EAnI-DpV3uT
PV Status allocatable
Total PE / Free PE 1279 / 1279

MÓDULO LVOL

Argumentos obligatorios
vg=nombre Nombre del grupo de volúmenes.
lv=nombre Nombre del volumen lógico.

186 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

Argumentos opcionales (Negrita indica el valor por defecto)


active yes Si debe estar activo o no.
no
force no Forzar reducir tamaño o eliminar.
yes
opts Opciones a pasar al commando lvcreate.
pvs Lista separada por comas de PVs.
shrink True Reducir tamaño del volumen lógico.
False
size Por defecto en megabytes, se puede
especificar unidad (bBsSkKmMgGtTpPeE) o
porcentaje de PV/PVS/FREE.
snapshot Nombre del snapshot del volumen.
state present Estado del volumen lógico.
absent

En el siguiente ejemplo se crea un volumen lógico de 2 gigabytes dentro del


grupo de volúmenes creado anteriormente con el módulo lvg.

Contenido del playbook.


- name: Crear un volumen lógico dentro del vg ansible
hosts: servidor
tasks:
- lvol:
vg: ansible
lv: libro
state: present
size: 2G
Comprobación del volumen lógico creado.
# lvdisplay ansible/libro
--- Logical volume ---
LV Path /dev/ansible/libro
LV Name libro
VG Name ansible
LV UUID g35qKF-A6wf-9Ae2-8qav-J26w-qiPN-vemujc
LV Write Access read/write
LV Creation host, time localhost.localdomain, 2018-03-20
17:38:41 +0000
LV Status available

© Alfaomega-RC Libros 187


ANSIBLE

# open 0
LV Size 2.00 GiB
Current LE 512
Segments 1
Allocation inherit
Read ahead sectors auto
- currently set to 8192
Block device 253:2

MÓDULO MODPROBE

Argumentos obligatorios
name=módulo Nombre del módulo Kernel.
Argumentos opcionales (Negrita indica el valor por defecto)
params Parámetros para el módulo.
state present Estado del módulo.
absent

En el siguiente ejemplo se carga el módulo bonding.

Contenido del playbook.


- name: Cargar módulo bonding
hosts: servidor
tasks:
- modprobe:
name: bonding
state: present
Comprobación que el módulo está cargado.
# lsmod | grep bonding
bonding 124989 0

MÓDULO MOUNT

Argumentos obligatorios
path=ruta Ruta donde montar el dispositivo.
state=estado present Estado del punto de montaje.
absent
mounted
unmounted

188 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

Argumentos opcionales (Negrita indica el valor por defecto)


boot yes Determina si debe ser montado al
no arrancar. Solo aplicable a Solaris
dump Campo dump de fstab.
fstab Fichero a usar en vez de /etc/fstab
fstype Tipo de sistema de ficheros.
opts Opciones de montaje.
passno Campo passno de fstab.
src Dispositivo a ser montado.

En el siguiente ejemplo se utilizan el volumen lógico y el sistema de ficheros


creado con los módulos lvol y filesystem para montarlo en un directorio.
Contenido completo del playbook.
- name: Crear y montar partición dentro de LVM
hosts: servidor
tasks:
- lvg:
vg: ansible
state: present
pvs:
- /dev/sdc
- /dev/sdd
- lvol:
vg: ansible
lv: libro
state: present
size: 2G
- name: Formatear partición
filesystem:
dev: /dev/ansible/libro
fstype: xfs
- name: Crear directorio destino
file:
path: /mnt/ansible
state: directory
- name: Montar partición
mount:
src: /dev/ansible/libro
path: /mnt/ansible
fstype: xfs
state: mounted

© Alfaomega-RC Libros 189


ANSIBLE

Comprobación después de ejecutarlo.


# df -hT /mnt/ansible/
Filesystem Type Size Used Avail Use% Mounted on
/dev/mapper/ansible-libro xfs 2.0G 33M 2.0G 2% /mnt/ansible
# grep ansible /etc/fstab
/dev/ansible/libro /mnt/ansible xfs defaults 0 0

MÓDULO PARTED

Argumentos obligatorios
device=dispositivo El dispositivo a tratar.
Argumentos opcionales (Negrita indica el valor por defecto)
align optimal Alineación de la partición.
none
cylinder
minimal
flags Lista de flags a especificar.
label msdos Crea una nueva etiqueta de disco.
aix
amiga
bsd
dvh
gpt
loop
mac
pc98
sun
name Especifica el nombre(GPT, Mac,
MIPS y PC98 sólo).
number El número de la partición.
part_end Terminación de la partición. P.e.
10GiB, 15%.

part_start Inicio de la partición. P.e.


10GiB, 15%.

part_type primary Tipo de partición.


extended
logical

190 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

state info Estado de la partición.


present
absent
unit s Unidad de tamaño para la
B partición.
KB/KiB
MB/MiB
GB/GiB
TB/TiB
%
cyl
chs
compact

En el siguiente ejemplo se crea una partición primaria utilizando todo el


espacio disponible (por defecto).
Playbook para crear una partición primaria en /dev/sda.
- name: Crear partición en /dev/sda
hosts: servidor
tasks:
- name: Crear partición primaria
parted:
device: /dev/sda
number: 1
state: present
Comprobación de la creación de la partición.
# fdisk -l /dev/sda
Disk /dev/sda: 5368 MB, 5368709120 bytes, 10485760 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0x000462cb
Device Boot Start End Blocks Id System
/dev/sda1 2048 10485759 5241856 83 Linux

MÓDULO SEBOOLEAN

Argumentos obligatorios
name=nombre Nombre del Boolean a configurar.
state=estado Valor del Boolean.

© Alfaomega-RC Libros 191


ANSIBLE

Argumentos opcionales (Negrita indica el valor por defecto)


persistent no Estado del Boolean.
yes

En el siguiente ejemplo se permite que el servidor web pueda realizar


conexiones a otros servidores, lo cual está deshabilitado por defecto al utilizar
SELinux.

Contenido del playbook.


- name: Permitir al servidor web conectarse a servidores
hosts: servidor
tasks:
- name: Instalar librería necesaria
yum:
name: libsemanage-python
state: present
- seboolean:
name: httpd_can_network_connect
state: yes
persistent: yes
Comprobación de la regla SElinux.
# getsebool httpd_can_network_connect
httpd_can_network_connect --> on

MÓDULO SEFCONTEXT

Argumentos obligatorios
setype=tipo Tipo SELinux para el destino especificado.
target=ruta Ruta de destino.
path=ruta
Argumentos opcionales (Negrita indica el valor por defecto)
ftype Tipo de fichero. Por defecto "a".
reload yes Releer política SELinux después de
no aplicarla.
selevel Rango SELinux para el destino
serange especificado.
seuser Usuario SELinux para el destino
especificado.

192 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

state present Estado deseado.


absent

En el siguiente ejemplo se establece el contexto de SElinux para un directorio y


poder ser utilizado por Apache en un directorio distinto al de por defecto
(/var/ww/html)

Contenido del playbook para establecer el contexto.


- name: Establecer contexto SElinux para ser usado por httpd
hosts: servidor
tasks:
- name: Instalar librería necesaria
yum:
name: policycoreutils-python
state: latest
- name: Establecer contexto
sefcontext:
target: '/web(/.*)?'
setype: httpd_sys_content_t
state: present
register: establecer_contexto
- name: Ejecutar restorecon si se cambia el contexto
command: restorecon -R -v /web
when: establecer_contexto|changed
Comprobación del contexto aplicado.
# ls -ldaZ /web/ /web/index.html
drwxr-xr-x. root root unconfined_u:object_r:httpd_sys_content_t:s0 /web/
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 /web/index.html

MÓDULO SELINUX

Argumentos obligatorios
state=estado enforcing Modo SELinux
permissive
disabled
Argumentos opcionales
conf Ruta al fichero de configuración SELinux. Por
defecto /etc/selinux/config
policy Nombre de la política SELinux a usar.

© Alfaomega-RC Libros 193


ANSIBLE

En el siguiente ejemplo cambiamos el modo de Enforcing a Permissive en el


sistema administrado.

Contenido del playbook.


- name: Establecer SElinux a modo permisivo
hosts: servidor
tasks:
- name: Instalar librería necesaria
yum:
name: policycoreutils-python
state: latest
- selinux:
policy: targeted
state: permissive
Comprobación del cambio.
# getenforce
Enforcing

# ansible-playbook selinux.yml
PLAY [Establecer SElinux a modo permisivo] ***
TASK [Gathering Facts] ****
ok: [servidor]
TASK [Instalar librería necesaria] **************
ok: [servidor]
TASK [selinux] ************
changed: [servidor]

PLAY RECAP ***********


servidor: ok=3 changed=1 unreachable=0 failed=0

# getenforce
Permissive

MÓDULO SELINUX_PERMISSIVE

Argumentos obligatorios
permissive=True/False Si el dominio debe ser permisivo o no.
domain=nombre El dominio a tratar.
Argumentos opcionales (Negrita indica el valor por defecto)
no_reload False Releer la política SELinux.
True

194 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

store Nombre del almacenamiento de la


política a utilizar.

En el siguiente ejemplo se establece el dominio httpd_t en modo permisivo. Es


importante tener cuidado con los dominios que se establecen como permisivos ya
que pueden crear una brecha de seguridad.

Contenido del playbook que establece a permisivo el dominio


httpd_t.
- name: Establecer el dominio httpd_t a modo permisivo
hosts: servidor
tasks:
- name: Instalar librería necesaria
yum:
name: policycoreutils-python
state: latest
- selinux_permissive:
domain: httpd_t
permissive: true
Comprobación después de ejecutar el playbook.
# semanage permissive -l
Customized Permissive Types
httpd_t
Builtin Permissive Types
sanlk_resetd_t
hsqldb_t
systemd_hwdb_t
blkmapd_t
ipmievd_t

MÓDULO SEPORT

Argumentos obligatorios
ports Puertos o rango de puertos separados por
coma.
proto tcp Protocolo a utilizar para el puerto.
udp
setype Tipo SELinux para el puerto.
state present El estado deseado.
absent

© Alfaomega-RC Libros 195


ANSIBLE

Argumentos opcionales
reload Recargar la política SELinux después de
aplicarla.

En el siguiente ejemplo permitimos que httpd (Apache) pueda escuchar en un


puerto distinto a los de por defecto (80, 81, 443, 488, 8008, 8009, 8443, 9000).

Playbook para permitir que httpd use el puerto 88.


- name: Permitir que httpd utilice el puerto 88
hosts: servidor
tasks:
- name: Instalar librerías necesarias
yum:
name: "{{ item }}"
state: latest
with_items:
- policycoreutils-python
- libselinux-python
- seport:
ports: 88
proto: tcp
setype: http_port_t
state: present
Comprobación de la aplicación de la regla.
# semanage port -l | grep ^http_port_t
http_port_t tcp 88, 80, 81, 443, 488, 8008, 8009, 8443, 9000

MÓDULO SERVICE

Argumentos obligatorios
name=nombre Nombre del servicio.
Argumentos opcionales (Negrita indica el valor por defecto)
arguments Argumentos adicionales.
args
enabled no Si debe iniciarse al arrancar el
yes sistema.
pattern Cadena a buscar si el servicio no
responde.
runlevel Para OpenRC init scripts.

196 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

sleep Tiempo a esperar entre la detención y


el arranque.
state started Estado del servicio.
stopped
restarted
reloaded
use El módulo a utilizar. Por defecto se
autodetecta.

En el siguiente ejemplo se inicia y se habilita el servicio httpd.


Contenido del playbook.
- name: Iniciar y activar el servicio httpd
hosts: servidor
tasks:
- name: Instalar httpd
yum:
name: httpd
state: latest
- name: Iniciar y habilitar
service:
name: httpd
state: started
enabled: true
Comprobación después de ejecutar el playbook.
# systemctl is-active httpd
active
# systemctl is-enabled httpd
enabled

MÓDULO SETUP
Argumentos opcionales (Negrita indica el valor por defecto)
fact_path Ruta donde se almacenan los facts locales. Por
defecto /etc/ansible/facts.d
filter Expresión para seleccionar facts. Por defecto
"*".
gather_subset Restringir subconjunto: all, min, hardware,
network, virtual, ohai, and factor. Se puede
utilizar admiración para ignorar un
subconjunto. Por defecto all.

© Alfaomega-RC Libros 197


ANSIBLE

gather_timeout Establecer el tiempo de espera máxima para


colectar los facts.

En el siguiente ejemplo se utiliza setup dos veces, la primera vez para obtener
toda la información (equivalente a gather_facts: True) y después de cambiar el
hostname con el módulo con el mismo nombre, se utiliza setup para obtener el
nuevo hostname.
Contenido del playbook.
- name: Cambiar el hostname y ejecutar setup
hosts: servidor
gather_facts: False
tasks:
- name: Ejecutar primer setup para obtener información.
setup:
- name: Mostrar el hostname antiguo
debug: var=ansible_fqdn
- name: Cambiar hostname
hostname:
name: libroansible.oforte.net
- setup:
filter: ansible_fqdn
- name: Mostrar el hostname nuevo
debug: var=ansible_fqdn
Resultado mostrado.
PLAY [Cambiar el hostname y ejecutar setup] **
TASK [Ejecutar primer setup para obtener información.] *****
ok: [servidor]
TASK [Mostrar el hostname antiguo] **********
ok: [servidor] => {
"ansible_fqdn": "localhost.localdomain"
}
TASK [Cambiar hostname] ****
changed: [servidor]
TASK [setup] *************
ok: [servidor]
TASK [Mostrar el hostname nuevo] ************
ok: [servidor] => {
"ansible_fqdn": "libroansible.oforte.net"
}

PLAY RECAP ************


servidor : ok=5 changed=1 unreachable=0 failed=0

198 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

MÓDULO SYSCTL

Argumentos obligatorios
name=nombre Clave separada por puntos.
key=nombre
Argumentos opcionales (Negrita indica el valor por defecto)
ignoreerrors no Ignorar errores si no existen claves.
yes
reload yes Si ejecutar /sbin/sysctl -p después de
no modificar el documento.
state present Estado de la clave en sysctl.
absent
sysctl_file Especifica la ruta, por defecto
/etc/sysctl.conf.
sysctl_set no Verifica el valor del código.
yes
value Valor para la clave.

En el siguiente ejemplo establecemos la variable net.ipv4.ip_forward para


permitir redirigir el tráfico en este servidor.

Contenido del playbook.


- name: Permitir redirigir tráfico
hosts: servidor
tasks:
- sysctl:
name: net.ipv4.ip_forward
value: 1
sysctl_set: yes
state: present
reload: yes
Comprobación después de ejecutar el playbook.
# sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1
# grep net.ipv4.ip_forward /etc/sysctl.conf
net.ipv4.ip_forward=1

© Alfaomega-RC Libros 199


ANSIBLE

MÓDULO SYSTEMD

Argumentos opcionales (Negrita indica el valor por defecto)


daemon_reload yes Ejecuta daemon-reload antes de
no realizar cualquier operación.
enabled yes Si el servicio debe ser arrancado al
no iniciar el sistema.
masked yes Si la unidad debe ser enmascarada.
no
name Nombre del servicio.
unit
service
no_block yes No esperar a que la operación
no solicitada finalice.
state started Estado del servicio.
stopped
restarted
reloaded
user yes El usuario con el que habla
no servicio.

En los siguientes ejemplos se muestran tareas comunes que se realizan en


systemd.

Instalar httpd e iniciar y habilitar el servicio.


- name: Iniciar y activar el servicio httpd
hosts: servidor
tasks:
- name: Instalar httpd
yum:
name: httpd
state: latest
- name: Iniciar y habilitar
systemd:
name: httpd
state: started
enabled: true
Releer la configuración después de cambiar la configuración.
- name: Copiar configuración de httpd y releer configuración
hosts: servidor

200 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

tasks:
- name: Copiar configuración
copy:
src: httpd.conf
dest: /etc/httpd/conf/httpd.conf
notify: releer_httpd
handlers:
- name: releer_httpd
systemd:
name: httpd
state: reloaded
Releer la configuración propia de systemd.

- name: Cambiar configuración del servicio de httpd


hosts: servidor
tasks:
- name: Copiar configuración del servicio
copy:
src: httpd.service
dest: /usr/lib/systemd/system/httpd.service
notify:
- releer_systemd
- reiniciar_httpd
handlers:
- name: releer_systemd
systemd:
daemon_reload: True
- name: reiniciar_httpd
systemd:
name: httpd
state: restarted

MÓDULO TIMEZONE

Argumentos opcionales
hwclock Si el reloj del servidor está en UTC o en zona
horaria local.
name Nombre de la zona horaria para el reloj del sistema.

En el siguiente ejemplo se establece la zona horaria a Europe/Madrid.

© Alfaomega-RC Libros 201


ANSIBLE

Contenido del playbook.


- name: Establecer timezone a Europe/Madrid
hosts: servidor
tasks:
- timezone:
name: Europe/Madrid
Comprobación después de ejecutar el playbook.
# timedatectl
Local time: Sat 2018-03-24 11:44:48 CET
Universal time: Sat 2018-03-24 10:44:48 UTC
RTC time: Sat 2018-03-24 10:44:48
Time zone: Europe/Madrid (CET, +0100)
NTP enabled: yes
NTP synchronized: yes
RTC in local TZ: no
DST active: no
Last DST change: DST ended at
Sun 2017-10-29 02:59:59 CEST
Sun 2017-10-29 02:00:00 CET
Next DST change: DST begins (the clock jumps one hour
forward) at
Sun 2018-03-25 01:59:59 CET
Sun 2018-03-25 03:00:00 CEST

MÓDULO USER

Argumentos obligatorios
name=nombre Nombre del usuario a crear, borrar o
user=nombre modificar.
Argumentos opcionales (Negrita indica el valor por defecto)
append no Indica si añadir los grupos a la
yes lista actual.
comment Comentario para el usuario.
createhome yes Si crea el directorio del usuario
no o no.
expires Fecha de expiración.
force no Fuerza la eliminación del
yes usuario.

202 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

generate_ssh_key no Si debe generar una clave SSH


yes (.no sobrescribirá si existe)
group Grupo primario.
groups Lista de grupos secundarios.
home Directorio del usuario.
local Fuerza el uso del comando "local"
en plataformas que lo
implementan.
login_class La clase del usuario en sistemas
FreeBSD, OpenBSD y NetBS.
move_home no Si el directorio home debe
yes moverse.
non_unique no Permite tener usuarios con el
yes mismo UID.
password Establece la contraseña del
usuario.
remove no Si usa userdel --remove.
yes
seuser Especifica el tipo de seuser
(user_u).
shell Especifica la shell en el
sistema.
skeleton Establece el directorio skeleton.
ssh_key_bits Especifica el número de its para
crear la clave SSH.
ssh_key_comment Comentario clave SSH. Por
defecto: ansible-generated on
$HOSTNAME
ssh_key_file Nombre del fichero para la clave
SSH.
ssh_key_passphr Establece la passphrase para la
ase clave SSH.
ssh_key_type Tipo de clave SSH a generar.
state present Estado del usuario.
absent
system no Si debe ser una cuenta de
yes sistema.

© Alfaomega-RC Libros 203


ANSIBLE

uid Identificador del usuario.


update_password always Indica si siempre se debe
on_create actualizar la contraseña con la
especificada.

En el siguiente ejemplo se crea un usuario con una contraseña predefinida.

Contenido del playbook.


- name: Crear un usuario en el sistema
hosts: servidor
tasks:
- name: Instalar librería para generar clave cifrada
pip:
name: passlib
state: latest
- name: Cifrar clave
command: python -c "from passlib.hash import sha512_crypt; print
sha512_crypt.using(rounds=5000).hash('clavesupersegura')"
register: clave_cifrada
- name: Crear usuario
user:
name: alberto
password: "{{ clave_cifrada.stdout }}"
state: present
comment: Usuario creado por Ansible
Comprobación de la creación del usuario.
# getent passwd alberto
alberto:x:1001:1001:Usuario creado por Ansible:/home/alberto:/bin/bash

MÓDULOS WINDOWS

Estos módulos son utilizados para gestionar el sistema operativo Windows. En


negrita se indican los módulos que se detallarán en profundidad.

Establecer permisos de archivo /


directorio / registro para un usuario
o grupo del sistema
win_acl
Cambia la herencia de ACL
win_acl_inheritance

204 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

win_chocolatey Administra paquetes usando chocolatey.


Ejecuta un comando en un nodo Windows
win_command remoto.
Copia archivos en ubicaciones remotas
win_copy en hosts de Windows.
Consolida archivos fragmentados en
win_defrag volúmenes locales.
Administra montajes ISO / VHD / VHDX
win_disk_image en hosts de Windows.
Configura la búsqueda de DNS en los
win_dns_client hosts de Windows.
Garantiza la existencia de un dominio
win_domain de Windows.
Administra el estado del servidor del
controlador de dominio / miembro para
win_domain_controller un host de Windows.
Crea, modifica o elimina grupos de
win_domain_group dominio.
Administra la pertenencia de dominio /
grupo de trabajo para un host de
win_domain_membership Windows.
Administra cuentas de usuario de
win_domain_user Windows Active Directory.
Ejecuta ngen para recompilar archivos
DLL después de las actualizaciones de
win_dotnet_ngen .NET.
Invoca una configuración DSC de
win_dsc PowerShell.
Modifica las variables de entorno en
win_environment los hosts de Windows.
Administra registros de eventos de
win_eventlog Windows.
Escribe entradas en los registros de
win_eventlog_entry eventos de Windows.

Instala y desinstala las


características de Windows en Windows
win_feature Server.

© Alfaomega-RC Libros 205


ANSIBLE

Crea, toca o elimina archivos o


win_file directorios.
Obtiene versión de compilación de
win_file_version archivo DLL o EXE.
Devuelve una lista de archivos basada
win_find en criterios específicos.
Habilita o deshabilita el firewall de
win_firewall Windows.
Automatización del firewall de
win_firewall_rule Windows.
Obtiene un archivo de una URL
win_get_url determinada.
win_group Agrega y elimina grupos locales.
Administra membresía de grupo local de
win_group_membership Windows.
Instala y desinstala las revisiones de
win_hotfix Windows.
Configura un directorio virtual en
win_iis_virtualdirectory IIS.
win_iis_webapplication Configura aplicaciones web de IIS.
Configura un grupo de aplicaciones web
win_iis_webapppool de IIS.
win_iis_webbinding Configura un sitio web de IIS.
win_iis_website Configura un sitio web de IIS.
Asegúrese de que una línea en
particular esté en un archivo, o
reemplace una línea existente usando
win_lineinfile un respaldo.
Mapea una unidad de red para un
win_mapped_drive usuario.
Envía un mensaje a los usuarios que
han iniciado sesión en los hosts de
win_msg Windows.
win_nssm NSSM.
win_owner Establece propietario.
Instala / desinstala un paquete
win_package instalable.

206 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

Consulta o cambia la configuración del


win_pagefile archivo de paginación.
Gestiona variables de entorno de ruta
win_path de Windows.
Una versión de Windows del módulo ping
win_ping clásico.
Cambia el plan de energía de un
win_power_plan sistema Windows.
Ejecuta comandos (de forma remota)
win_psexec como otro usuario (privilegiado).
win_psmodule Agrega o quita un módulo Powershell.
win_rabbitmq_plugin Administra complementos de RabbitMQ.
win_reboot Reinicia una máquina de Windows.
Devuelve información sobre una clave
de registro de Windows o propiedad de
win_reg_stat una clave.
Agrega, cambia o elimina claves de
win_regedit registro y valores.
Establece la región y la configuración
win_region de formato.
Fusiona el contenido de un archivo de
win_regmerge registro en el registro de Windows.
Sincroniza los contenidos de dos
win_robocopy directorios usando Robocopy.
win_route Agregue o elimine una ruta estática.
Módulo de texto a voz para que Windows
emita mensajes y, opcionalmente,
win_say reproduzca sonidos.
win_scheduled_task Administra tareas programadas.
Cambia la configuración de la política
win_security_policy de seguridad local.
win_service Administra los servicios de Windows.
win_share Administra acciones de Windows.
Ejecuta comandos de shell en los hosts
win_shell de destino.
win_shortcut Administra atajos en Windows.

© Alfaomega-RC Libros 207


ANSIBLE

Devuelve información sobre un archivo


win_stat de Windows.
Crea archivos y directorios
win_tempfile temporales.
Procesa plantillas y las transfiere a
win_template un servidor remoto.
Establece la zona horaria de la
win_timezone máquina de Windows.
Envía notificaciones de ventanas de
Toast a usuarios conectados en Windows
win_toast 10 o hosts posteriores.
Descomprime archivos y archivos
win_unzip comprimidos en el nodo de Windows.
Descarga e instala las actualizaciones
win_updates de Windows.
win_uri Interactúa con los servicios web.
Administra las cuentas de usuario
win_user locales de Windows.
Administra los derechos de usuario de
win_user_right Windows.
Espera una condición antes de
win_wait_for continuar.
win_wakeonlan Envía un Wake mágico.
Instala paquetes usando el comando Web
win_webpicmd Platform Installer.

En los siguientes ejemplos se utiliza el servidor llamado "windows01" con las


variables indicadas:

ansible_host 35.196.65.128
ansible_connection winrm
ansible_winrm_server_cert_validation ignore
ansible_user alberto
ansible_password clave_usuario_alberto

Dicho servidor tiene habilitado en las reglas de firewall el puerto 5986 (TCP)
para WinRM. Para habilitar la administración remota se utilizó PowerShell con el

208 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

siguiente script:
https://raw.githubusercontent.com/ansible/ansible/devel/examples/scripts/Confi
gureRemotingForAnsible.ps1

MÓDULO WIN_PING

Este módulo sirve para comprobar la conexión al servidor (acceso a WinRM y


autenticación).

# ansible -i inventario_windows windows01 -m win_ping


windows01 | SUCCESS => {
"changed": false,
"ping": "pong"
}

MÓDULO WIN_CHOCOLATEY

Argumentos obligatorios
name=nombre Nombre del paquete a instalar.
Argumentos opcionales (Negrita indica el valor por defecto)
allow_empty_checksums no Permite checksums vacíos.
yes
force no Fuerza la instalación.
yes
ignore_checksums no Ignora el checksum.
yes
ignore_dependencies no Ignora dependencias.
yes
install_args Argumentos a pasar al
instalador.
params Parámetros a pasar al
programa.
proxy_password Clave del proxy.
proxy_url Dirección del proxy.
proxy_username Usuario del proxy.
skip_scripts no No ejecutar
yes chocolateyInstall.ps1 o
chocolateyUninstall.ps1.

© Alfaomega-RC Libros 209


ANSIBLE

source Especifica el origen.


state present Estado del paquete en el
absent sistema.
downgrade
latest
reinstalled
timeout Tiempo máximo de espera.
execution_timeout Por defecto 2700.
upgrade no Si el paquete debe ser
yes actualizado o no.
version Versión a instalar.

En el siguiente ejemplo instalamos un software usando chocolatey.

Instalar git usando el módulo win_chocolatey.


- name: Instalar git usando chocolatey
hosts: windows01
gather_facts: False
tasks:
- win_chocolatey:
name: git
state: latest
Comprobación después de ejecutarlo.
PLAY [Instalar git usando chocolatey] *********
META: ran handlers
TASK [win_chocolatey] **
task path: /tmp/chocolatey.yml:5
Using module file /usr/local/lib/python2.7/dist-
packages/ansible/modules/windows/win_chocolatey.ps1
<35.196.192.219> ESTABLISH WINRM CONNECTION FOR USER: alberto on PORT 5986
TO 35.196.192.219
EXEC (via pipeline wrapper)
[WARNING]: Chocolatey was missing from this system, so it was installed
during this task run.
changed: [windows01] => {
"changed": true,
"rc": 0,
"stdout": "(omitido)"
"stdout_lines": [
"Installing the following packages:",
"git",

210 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

"By installing you accept licenses for the packages.",


"",
"chocolatey-core.extension v1.3.3 [Approved]",
"chocolatey-core.extension package files install completed. Performing
other installation steps.",
" Installed/updated chocolatey-core extensions.",
" The install of chocolatey-core.extension was successful.",
" Software installed to
'C:\\ProgramData\\Chocolatey\\extensions\\chocolatey-core'",
"",
(omitido)
" The install of git.install was successful.",
" Software installed to 'C:\\Program Files\\Git\\'",
"",
"git v2.16.3 [Approved]",
"git package files install completed. Performing other installation
steps.",
" The install of git was successful.",
"Chocolatey installed 3/3 packages. ",
" See the log for details
(C:\\ProgramData\\Chocolatey\\logs\\chocolatey.log)."
]
}

PLAY RECAP ************


windows01 : ok=1 changed=1 unreachable=0 failed=0

MÓDULO WIN_COMMAND

Argumentos obligatorios
comando El comando a ejecutar.
Argumentos opcionales (Negrita indica el valor por defecto)
chdir El directorio a donde se mueve antes de ejecutar
el comando.
creates Si el fichero indicado existe no se ejecutará el
comando.
removes Si el fichero indicado no existe no se ejecutará
el comando.

En el siguiente ejemplo se ejecuta un comando y se muestra el resultado.

© Alfaomega-RC Libros 211


ANSIBLE

Playbook para mostrar el nombre del servidor Windows.


- name: Mostrar nombre del servidor
hosts: windows01
gather_facts: False
tasks:
- name: Ejecutar hostname
win_command: hostname
register: nombre_servidor
- debug: var=nombre_servidor.stdout
Resultado de la ejecución.
PLAY [Mostrar nombre del servidor] **********
TASK [Ejecutar hostname] *****
changed: [windows01]
TASK [debug] ************
ok: [windows01] => {
"nombre_servidor.stdout": "windows01\r\n"
}

PLAY RECAP *************


windows01 : ok=2 changed=1 unreachable=0 failed=0

MÓDULO WIN_COPY

Argumentos obligatorios
src=origen Ruta al fichero a copiar al servidor Windows.
dest=destino Ruta absoluta del fichero destino.
Argumentos opcionales (Negrita indica el valor por defecto)
content Se puede especificar esta opción en vez de
src para fijar el contenido.
force yes Sobrescribe el fichero destino si existe.
no
local_follow yes Si debe seguir enlaces simbólicos.
no
remote_src no Indica si la ruta origen ya está en el nodo
yes remoto administrado.

En el siguiente ejemplo se copia un fichero de hosts a un nodo Windows.

212 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

Contenido del playbook.


- name: Copiar fichero hosts a un nodo Windows
hosts: windows01
tasks:
- win_copy:
src: httpd.conf
dest: C:\Aplicaciones\httpd\conf\httpd.conf

MÓDULO WIN_ENVIRONMENT

Argumentos obligatorios
level=nivel machine El nivel donde se establecerá la
process variable de entorno.
user
name=nombre Nombre de la variable de entorno.
Argumentos opcionales (Negrita indica el valor por defecto)
state present Estado de la variable de entorno.
absent
value Valor de la variable de entorno.

En el siguiente ejemplo se establece la variable de entorno JAVA_HOME a la


ruta donde está instalado JDK 1.8.

Contenido del playbook.


- name: Establecer JAVA_HOME en Windows
hosts: windows01
tasks:
- win_environment:
state: present
name: JAVA_HOME
value: c:\Aplicaciones\jdk1.8
level: user
- setup:
filter: ansible_env
- debug: var=ansible_env
Comprobación de la variable de entorno.
PLAY [Establecer JAVA_HOME en Windows] **
TASK [Gathering Facts] ****
ok: [windows01]

© Alfaomega-RC Libros 213


ANSIBLE

TASK [win_environment] ***


changed: [windows01]
TASK [setup] *************
ok: [windows01]
TASK [debug] *************
ok: [windows01] => {
"ansible_env.JAVA_HOME": "c:\\Aplicaciones\\jdk1.8"
}
PLAY RECAP ************
windows01 : ok=4 changed=0 unreachable=0 failed=0

MÓDULO WIN_FEATURE

Argumentos obligatorios
name=nombre Nombre de la característica.
Argumentos opcionales (Negrita indica el valor por defecto)
include_manage True Incluir herramientas de
ment_tools False administración.
include_sub_fe True
Incluye subcaracterísticas.
atures False
source Origen de la característica.
present
state Estado de la característica.
absent

En el siguiente ejemplo se instala la característica de servidor web.

Contenido del playbook para habilitarlo.


- name: Añadir la característica de IIS
hosts: windows01
tasks:
- name: Habilitar la feature Web-Server
win_feature:
name: Web-Server
state: present

Comprobación de que el servidor web responde.


# curl -v http://35.196.65.128
> GET / HTTP/1.1
> User-Agent: curl/7.38.0
> Host: 35.196.65.128

214 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

> Accept: */*


>
< HTTP/1.1 200 OK
< Content-Type: text/html

< Server: Microsoft-IIS/10.0


[...]

MÓDULO WIN_FILE

Argumentos obligatorios
path=ruta Ruta al fichero a administrar.
dest=ruta
name=ruta
Argumentos opcionales (Negrita indica el valor por defecto)
state file Estado/tipo del fichero a administrar.
directory
touch
absent

En el siguiente ejemplo nos aseguramos de que un directorio exista.

Crear directorio para la aplicación httpd.


- name: Crear directorio para httpd
hosts: windows01
tasks:
- name: Crear directorio
win_file:
path: c:\aplicaciones\httpd
state: directory

MÓDULO WIN_FIREWALL

Argumentos opcionales (Negrita indica el valor por defecto)


profiles Domain El perfil o perfiles a modificar.
Private
Public
state enabled El estado del perfil.
disabled

© Alfaomega-RC Libros 215


ANSIBLE

En el siguiente ejemplo deshabilitamos todos los perfiles del cortafuegos de


Windows.

Contenido del playbook.


- name: Deshabilitar firewall de Windows
hosts: windows01
tasks:
- name: Deshabilitar todos los firewall
win_firewall:
name: "{{ item }}"
state: disabled
with_items:
- Domain
- Private
- Public
Comprobación de la deshabilitación.

MÓDULO WIN_FIREWALL_RULE

Argumentos obligatorios
action=acción allow Acción a hacer.
block
bypass
direction=direcció in Indicar si es de entrada o de
n out sl
name=nombre Nombre de la regla.
Argumentos opcionales (Negrita indica el valor por defecto)
description Descripción de la regla.
enabled yes Si la regla debe estar habilitada o
no no.

216 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

localip La ip local que aplica esta regla.


localport El puerto local que aplica a esta
regla.
profiles domain El perfil a asociar esta regla.
private
public
program El programa que aplica a esta regla.
protocol El protocolo que aplica a esta
regla.
remoteip La dirección remota que aplica.
remoteport El puerto remoto que aplica.
service El servicio al que se aplica.
state present El estado de la regla.
absent

En el siguiente ejemplo se muestra cómo habilitar los puertos 80 (http) y 443


(https) en el firewall.

Contenido del playbook.


- name: Permitir acceso a los puertos 80 y 443
hosts: windows01
tasks:
- name: Crear reglas en el firewall
win_firewall_rule:
name: "{{ item.nombre }}"
localport: "{{ item.puerto }}"
action: allow
direction: in
protocol: tcp
state: present
enabled: yes
with_items:
- {nombre: "Permitir HTTP", puerto: 80}
- {nombre: "Permitir HTTPS", puerto: 443}
Comprobación de las reglas creadas.

© Alfaomega-RC Libros 217


ANSIBLE

MÓDULO WIN_GROUP

Argumentos obligatorios
name=nombre Nombre del grupo
Argumentos opcionales (Negrita indica el valor por defecto)
description Descripción del grupo.
state present Estado del grupo.
absent

En el siguiente ejemplo se crea un grupo llamado "ansible".


Contenido del playbook.
- name: Crear grupo llamado ansible
hosts: windows01
tasks:
- name: Crear grupo
win_group:
name: "ansible"
description: Grupo creado por Ansible
state: present
Comprobación del grupo creado.

218 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

MÓDULO WIN_LINEINFILE

Argumentos obligatorios
path=ruta Ruta del fichero a modificar.
Argumentos opcionales (Negrita indica el valor por defecto)
backrefs no Especifica si la expresión puede
yes contener referencias anteriores.
create no Especifica si el fichero debe ser
yes creado si no existe.
insertafter EOF Si se especifica, se insertará
*regex* después de la línea encontrada con
dicha expresión. Si no se
especifica, se insertará al final
del fichero.
insertbefore BOF Si se especifica, se insertará
*regex* antes de la línea encontrada con
dicha expresión. Si no se
especifica, se insertará al final
del fichero.
line La línea a insertar o reemplazar.
regexp La expresión regular a buscar en
cada línea del fichero.
state present Indica si la línea debe estar en el
absent fichero o no.

En el siguiente ejemplo se modifica el fichero ports.conf para habilitar el


puerto 8080.

Habilitar el puerto 8080 en la configuración de Apache.


- name: Configurar el fichero ports.conf
hosts: windows01
tasks:
- name: Añadir la línea si no existe
win_lineinfile:
path: c:\aplicaciones\httpd\conf.d\ports.conf
line: "Listen 8080"
insertafter: "^Listen 80$"

© Alfaomega-RC Libros 219


ANSIBLE

Contenido del fichero ports.conf después de ejecutar el


playbook.
Listen 80
Listen 8080
<IfModule ssl_module>
Listen 443
</IfModule>

MÓDULO WIN_PACKAGE

Argumentos opcionales (Negrita indica el valor por defecto)


arguments Argumentos para el instalador.
creates_path Ruta para comprobar si el
paquete se instaló
correctamente.
creates_service Comprobar servicio para saber
si está instalado
correctamente.
creates_version Comprobar versión de fichero
para saber si está instalado
correctamente.
expected_return_code Código devuelto por el
instalador para saber si está
instalado correctamente.
name Nombre del paquete.
password Contraseña del usuario a
instalarlo.
path Ruta del paquete a ser
instalado o desinstalado.
product_id ID del producto instalado.
state present Estado del paquete.
absent
username Usuario con el que instalarlo.
validate_certs yes Comprobar certificados SSL.
no

En el siguiente ejemplo se instala el software Notepad++ usando Ansible.

220 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

Contenido del playbook que descarga e instala Notepad++.


- name: Instalar Notepad++
hosts: windows01
tasks:
- name: Descargar e instalar
win_package:
path: https://notepad-plus-
plus.org/repository/7.x/7.5.6/npp.7.5.6.Installer.x64.exe
product_id: Notepad++
arguments: /S
state: present
Comprobación de la instalación.

MÓDULO WIN_SERVICE

Argumentos obligatorios
name=nombre Nombre del servicio
Argumentos opcionales (Negrita indica el valor por defecto)
dependencies Lista de dependencias

© Alfaomega-RC Libros 221


ANSIBLE

dependency_action set Acción para las dependencias.


add
remove
description Descripción para el servicio.

desktop_interact Si debe interactuar con el


Desktop.
display_name Nombre a mostrar del servicio.

force_dependent_s False Fuerza a tratar los servicios


ervices True dependientes.

password Contraseña a establecer para el


servicio.
path Ruta del ejecutable.

start_mode auto Modo de inicio del servicio.


manual
disabled
delayed
state started Estado del servicio.
stopped
restarted
absent
paused
username Nombre de usuario a usar para
ejecutar el servicio.

En el siguiente ejemplo se detiene y se deshabilita un servicio de Windows.

Contenido del playbook.


- name: Detener y deshabilitar servicio "Themes"
hosts: windows01
tasks:
- name: Detener y deshabilitar
win_service:
name: Themes
state: stopped
start_mode: disabled

222 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

Comprobación del estado del servicio.

MÓDULO WIN_TEMPLATE

Argumentos obligatorios
src=ruta Ruta de la plantilla Jinja2.
dest=ruta Destino donde la plantilla procesada será
copiada.
Mismas opciones que el módulo template

En el siguiente ejemplo utilizamos una plantilla para generar información de


utilidad dentro del fichero /etc/issue:

Plantilla (index.html.j2) utilizada para generar el fichero


index.html.
System Information For Hostname: {{ inventory_hostname }}
Distribution: {{ ansible_os_name }}
Distribution Release: {{ ansible_distribution_version }}
Distribution Version: {{ ansible_distribution_major_version }}

© Alfaomega-RC Libros 223


ANSIBLE

IP Address: {{ ansible_ip_addresses|join (",") }}


DNS DOMAIN: {{ ansible_interfaces[0].dns_domain }}
Memory Installed: {{ (ansible_memtotal_mb / 1024) | round(1) }}GB
Memory Swapfile: {{ (ansible_swaptotal_mb / 1024) | round(1) }}GB
Processors: {{ ansible_processor_vcpus }}
Playbook para utilizar dicha plantilla para generar
/etc/issue.
- name: Copiar la plantilla index.html
hosts: windows01
tasks:
- name: Copiar plantilla
win_template:
src: index.html.j2
dest: C:\inetpub\wwwroot\index.html
Resultado ejemplo del fichero generado.
# curl http://35.196.65.128
System Information For Hostname: windows01
Distribution: Microsoft Windows Server 2016 Datacenter
Distribution Release: 10.0.14393.0
Distribution Version: 10
IP Address: 10.142.0.3
DNS DOMAIN: c.oforte-196215.internal
Memory Installed: 15.0GB
Memory Swapfile: 0.0GB
Processors: 4

MÓDULO WIN_USER

Argumentos obligatorios
name=nombre Nombre del usuario a crear, modificar o
eliminar.
Argumentos opcionales (Negrita indica el valor por defecto)
account_disabled no Si la cuenta debe ser
yes deshabilitada.
account_locked no Si la cuenta está
yes bloqueada.
description Descripción del usuario.
fullname Nombre completo del
usuario.

224 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

groups Indica los grupos del


usuario a añadir o
borrar.

groups_action replace Acción a realizar con los


add grupos especficados.
remove
password Contraseña del usuario en
texto plano.
password_expired no Si el usuario debe
yes cambiar la contraseña en
el primer login.

password_never_expires yes Si la clave nunca expira.


no
state present Estado del usuario.
absent
query
update_password always Indica si debe
on_create actualizarse siempre la
contraseña.

user_cannot_change_pass no Indica si el usuario


word yes puede cambiar la
contraseña.

En el siguiente ejemplo se crea un usuario y se le asigna al grupo previamente


creado (ansible).
Contenido del playbook.

- name: Crear usuario libro dentro del grupo ansible


hosts: windows01
tasks:
- name: Crear usuario
win_user:
name: libro
groups: ansible
description: Usuario creado con Ansible
password: "Libr0$Ansible"
state: present

© Alfaomega-RC Libros 225


ANSIBLE

Comprobación del usuario creado.

MÓDULOS CONTROL DE VERSIONES


Estos módulos sirven para gestionar diferentes plataformas de control de
versiones.

bzr Implementa software (o archivos) desde


sucursales bzr.
git Implementa software (o archivos) de las
cajas git.
git_config Lee y escribe la configuración de git.
github_deploy_key Administra las teclas de despliegue para
los repositorios de GitHub.
github_hooks Administra los enganches de servicio
GitHub.
github_issue Ve el problema de GitHub.
github_key Administra las claves de acceso de GitHub.
github_release Interactúa con las versiones de GitHub.
gitlab_group Crea / actualiza / elimina grupos de
Gitlab.
gitlab_project Crea / actualiza / elimina proyectos de
Gitlab.
gitlab_user Crea / actualiza / elimina usuarios de
Gitlab.
hg Administra los repositorios Mercurial
(hg).
subversion Implementa un repositorio de subversión.

226 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

MÓDULO BZR

En el siguiente ejemplo se descarga el código fuente de Emacs utilizando bzr.

Instalar bzr y descargar el código fuente de wget.


- name: Instalar bzr y descargar repositorio
hosts: servidor
tasks:
- name: Instalar bzr
apt:
name: bzr
state: latest
- name: Descargar wget
bzr:
name: http://bzr.savannah.gnu.org/r/wget/trunk
dest: /usr/src/wget
Comprobación de la descarga.
# ls /usr/src/wget/
ABOUT-NLS AUTHORS bootstrap bootstrap.conf build-aux cfg.mk
ChangeLog ChangeLog.README configure.ac COPYING doc lib m4
MAILING-LIST Makefile.am msdos NEWS po README
README.checkout src tests util vms

MÓDULO GIT

En el siguiente ejemplo descargamos los playbook de ejemplo oficiales de


Ansible.

Contenido del playbook.


- name: Instalar git y descargar repositorio
hosts: servidor
tasks:
- name: Instalar git
apt:
name: git
state: latest
- name: Descargar ejemplos de ansible
git:
name: https://github.com/ansible/ansible-examples.git
dest: /usr/src/ansible-examples

© Alfaomega-RC Libros 227


ANSIBLE

Directorio de comprobación.
# ls -1 /usr/src/ansible-examples/
jboss-standalone
lamp_haproxy
lamp_simple
lamp_simple_rhel7
language_features
mongodb
README.md
tomcat-memcached-failover
tomcat-standalone
windows
wordpress-nginx
wordpress-nginx_rhel7

MÓDULO GIT_CONFIG

En el siguiente ejemplo se configura el editor por defecto al programa vim a


nivel de sistema.

Contenido del playbook.


- name: Configurar el editor vim por defecto en el sistema
hosts: servidor
tasks:
- git_config:
name: core.editor
scope: system
value: vim
Comprobación del cambio en el fichero /etc/gitconfig.
# cat /etc/gitconfig
[core]
editor = vim

MÓDULO GITHUB_DEPLOY_KEY

En el siguiente ejemplo se añade la clave ssh pública del usuario que ejecuta el
playbook a un repositorio de GitHub.

Contenido del playbook.


- name: Añadir clave pública a github
hosts: localhost

228 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

gather_facts: False
tasks:
- name: Obtener clave del usuario
command: cat ~/.ssh/id_rsa.pub
register: myclave
- name: Añadir clave pública
github_deploy_key:
owner: "agonzalezrh"
repository: "libro-ansible"
name: "clave-ansible"
key: "{{ myclave.stdout }}"
force: yes
token: "7a9877d7b2ee82683925e61b0f23d9b0d9336"
Comprobación de la acción.

MÓDULO GITHUB_KEY

En el siguiente ejemplo se añade una clave pública a nuestra cuenta (esta clave
no debe estar asociada como clave de despliegue en un proyecto).

Contenido del playbook.


- name: Añadir clave pública a github

© Alfaomega-RC Libros 229


ANSIBLE

hosts: localhost
gather_facts: False
tasks:
- name: Obtener clave del usuario
command: cat /home/alberto/.ssh/id_rsa.pub
register: myclave
- name: Añadir clave pública
github_key:
name: "clave-publica-ansible"
pubkey: "{{ myclave.stdout }}"
token: "7a98d7b2ee82683925e61b0f23d9b0d9336"
Comprobación de la creación de la clave pública.

MÓDULO GITHUB_HOOKS

En el siguiente ejemplo se crea un webhook para hacer una llamada


automática a Jenkins.

Contenido del playbook.


- name: Crear un webhook en github
hosts: localhost
gather_facts: False
tasks:
- name: Crear webhook a jenkins
github_hooks:
action: create
hookurl: https://jenkins.oforte.net/github-webhook/
user: 'agonzalezrh'

230 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

oauthkey: '7ab2ee82683925e61b0f23d9b0d9336'
repo: https://api.github.com/repos/agonzalezrh/libro-ansible
Comprobación de la creación del hook.

MÓDULO GITHUB_RELEASE

En el siguiente ejemplo se crea un nuevo release y se obtiene información de la


misma.

Contenido del playbook.


- name: Crear un nuevo release y comprobar
hosts: localhost
gather_facts: False
tasks:
- name: Instalar librería necesaria
pip:
name: github3.py
state: latest
- name: Crear release
github_release:
token: 7ad7b2ee82683925e61b0f23d9b0d9336
user: agonzalezrh
repo: libro-ansible
action: create_release
tag: v0.1
target: master
name: Primer release de libro-ansible
body: Creado automáticamente por Ansible

- name: Obtener información del release creado


github_release:
token: 7ab2ee82683925e61b0f23d9b0d9336

© Alfaomega-RC Libros 231


ANSIBLE

user: agonzalezrh
repo: libro-ansible
action: latest_release
register: informacion_release

- debug: var=informacion_release
Mensaje mostrado por debug.
TASK [debug] ************
ok: [localhost] => {
"informacion_release": {
"changed": false,
"failed": false,
"tag": "v0.1"
}
}

Comprobación en Github.

MÓDULO GITLAB_GROUP

En el siguiente ejemplo se crea un grupo llamado ansible dentro de una


instalación propia de Gitlab.

232 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

Contenido del playbook.


- name: Crear grupo en gitlab para ser utilizado
hosts: localhost
gather_facts: False
tasks:
- name: Instalar librería necesaria
pip:
name: pyapi-gitlab
state: latest
- name: Crear grupo llamado ansible
gitlab_group:
server_url: https://gitlab.oforte.net
login_token: xnZWik-ugTYFBX-5Fsg8
name: ansible
path: ansible
Comprobación de la creación del grupo.

MÓDULO GITLAB_PROJECT

En el siguiente ejemplo se crea un proyecto llamado libro-ansible dentro del


grupo ansible.

Contenido del playbook.


- name: Crear proyecto en gitlab
hosts: localhost
gather_facts: False
tasks:
- name: Instalar librería necesaria
pip:
name: pyapi-gitlab
state: latest
- name: Crear proyecto
gitlab_project:
server_url: https://gitlab.oforte.net
login_token: xnZWik-ugTYFBX-5Fsg8

© Alfaomega-RC Libros 233


ANSIBLE

name: libro-ansible
group: ansible
issues_enabled: False
wiki_enabled: True
snippets_enabled: True
state: present
Comprobación de la creación del proyecto.

MÓDULO GITLAB_USER

En el siguiente ejemplo se crea un usuario dentro del grupo ansible creado


anteriormente. Además, se asocia una clave SSH para poder acceder al sistema
con ella.

Contenido del playbook.


- name: Crear usuario en gitlab y asignar a grupo ansible
hosts: localhost
gather_facts: False
tasks:
- name: Instalar librería necesaria
pip:
name: pyapi-gitlab
state: latest
- name: Obtener clave del usuario
command: cat /home/alberto/.ssh/id_rsa.pub
register: miclave

- name: Crear usuario


gitlab_user:
server_url: https://gitlab.oforte.net
login_token: xnZWik-ugTYFBX-5Fsg8
name: Alberto González
username: agonzalez
password: l1br04ns1bl3
email: alberto@oforte.net

234 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

sshkey_name: agonzalez
sshkey_file: "{{ miclave.stdout }}"
group: ansible
access_level: master
state: present
Comprobación de la creación del usuario.

MÓDULO HG

En el siguiente ejemplo se descarga la librería pygame de un repositorio desde


bitbucket.

© Alfaomega-RC Libros 235


ANSIBLE

Contenido del playbook.


- name: Instalar mercurial y descargar repositorio
hosts: localhost
tasks:
- name: Instalar mercurial
apt:
name: mercurial
state: latest
- name: Descargar pygame
hg:
name: https://bitbucket.org/pygame/pygame
dest: /usr/src/pygame
Comprobación de la descarga.
/usr/src/pygame# hg summary
parent: 3651:48e19c7b9ee9 tip
readme.rst edited online with Bitbucket
branch: default
commit: (clean)
update: (current)

MÓDULO SUBVERSION

En el siguiente ejemplo descargamos el popular software llamado wordpress


usando subversion.

Contenido del playbook.


- name: Instalar subversion y descargar repositorio
hosts: servidor
tasks:
- name: Instalar subversion
apt:
name: subversion
state: latest
- name: Descargar Wordpress
subversion:
name: https://core.svn.wordpress.org/trunk/
dest: /usr/src/wordpress
Comprobación de la descarga.
# svn info
Path: .
Working Copy Root Path: /usr/src/wordpress

236 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

URL: https://core.svn.wordpress.org/trunk
Relative URL: ^/trunk
Repository Root: https://core.svn.wordpress.org
Repository UUID: 1a063a9b-81f0-0310-95a4-ce76da25c4cd
Revision: 42720
Node Kind: directory
Schedule: normal
Last Changed Author: SergeyBiryukov
Last Changed Rev: 42720
Last Changed Date: 2018-03-29 01:25:29 +0200 (Thu, 29 Mar
2018)

MÓDULOS INFRAESTRUCTURA WEB


Estos módulos sirven para gestionar diferentes aplicaciones de infraestructura
web.

Establece y / o obtiene los atributos de


los miembros de un grupo equilibrador
apache2_mod_proxy Apache httpd 2.4 mod_proxy
Habilita / deshabilita un módulo del
apache2_module servidor web Apache2
Gestiona algunos de los pasos comunes en
deploy_helper la implementación de proyectos.
django_manage Administra una aplicación de Django.
Administra usuarios para servidores
ejabberd_user ejabberd.
Ejecuta gunicornio con varias
gunicorn configuraciones.
Administra archivos de usuario para
htpasswd autenticación básica.
jboss Implementa aplicaciones en JBoss.
jenkins_job Administra trabajos Jenkins.
jenkins_plugin Agrega o elimina el plugin de Jenkins.
Ejecuta una secuencia de comandos groovy
jenkins_script en la instancia de Jenkins.
Crea y modifica problemas en una
jira instancia de JIRA.

© Alfaomega-RC Libros 237


ANSIBLE

letsencrypt Crea certificados SSL con Let's Encrypt.


nginx_status_facts Recupera hechos del estado de nginx.
Administra las políticas de ACL de
rundeck_acl_policy Rundeck.
rundeck_project Administra proyectos Rundeck.
Administra el estado de un programa o
grupo de programas que se ejecutan a
supervisorctl través de supervisord.
Crea / elimina un problema en una
plataforma de gestión de proyectos de
taiga_issue Taiga.

MÓDULO APACHE2_MODULE

Este módulo requiere que las aplicaciones a2enmod y a2dismod estén


disponibles en el sistema. En el siguiente ejemplo se habilita el módulo userdir.

Contenido del playbook.


- name: Habilitar el módulo userdir
hosts: servidor
tasks:
- name: Habilitar userdir
apache2_module:
name: userdir
state: present
Comprobar que el módulo userdir está cargado.
# apache2ctl –M | grep userdir
userdir_module (shared)

MÓDULO HTPASSWD

En el siguiente ejemplo se crea un usuario dentro de un fichero con formato


htpasswd.

Contenido del playbook.


- name: Crear usuario en fichero htpasswd
hosts: servidor
tasks:
- htpasswd:

238 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

path: /etc/apache2/usuarios
name: ansible
password: 'l1br04ns1bl3'
owner: root
group: www-data
mode: 0640
Comprobación de la creación del usuario.
# cat /etc/apache2/usuarios
ansible:$apr1$YriaRg9u$/HiXRBkwfM60UWsj6I5li.

MÓDULO JBOSS

En el siguiente ejemplo se despliega la aplicación Jolokia que sirve para


monitorizar el estado.

Contenido del playbook.


- name: Desplegar jolokia
hosts: servidor
tasks:
- jboss:
src: /tmp/jolokia-war-1.5.0.war
deploy_path:
/opt/rh/eap7/root/usr/share/wildfly/standalone/deployments
deployment: jolokia.war
state: present
Comprobación de la instalación de jolokia.
# curl -s http://localhost:8080/jolokia | jq
{
"request": {
"type": "version"
},
"value": {
"agent": "1.5.0",
"protocol": "7.2",
"config": {
[..]
},
"info": {
"product": "JBoss EAP",
"vendor": "RedHat",
"version": "7.1.1.GA"
}

© Alfaomega-RC Libros 239


ANSIBLE

},
"timestamp": 1522418397,
"status": 200
}

MÓDULO JENKINS_JOB

Crear un nuevo job clonando uno existente.

Contenido del playbook.


- name: Clonar job de jenkins
hosts: servidor
gather_facts: False
tasks:
- name: Leer configuración
command: curl -s
https://admin:cdd5e29337e268c133d7cf35727461fe@jenkins.ofort
e.net/job/libro-ansible-job/config.xml
register: configuracion

- name: Instalar librería necesaria


pip:
name: python-jenkins
state: latest

- name: Añadir job


jenkins_job:
config: "{{ configuracion.stdout }}"
name: libro-ansible-job-copia
token: cdd5e29337e268c133d7cf35727461fe
url: https://jenkins.oforte.net
user: admin
Comprobación de que se ha clonado correctamente.

240 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

MÓDULO JENKINS_PLUGIN

En el siguiente ejemplo habilitamos el plugin build-pipeline-plugin.

Contenido del playbook.


- name: Habilitar plugin build-pipeline-plugin
hosts: localhost
tasks:
- name: Habilitar plugin
jenkins_plugin:
name: build-pipeline-plugin
url: https://jenkins.oforte.net
url_username: admin
url_password: cdd5e29337e268c133d7cf35727461fe

- name: Reiniciar jenkins


service:
name: jenkins
state: restarted

Comprobación del plugin instalado.

MÓDULO JIRA

En el siguiente ejemplo se crea una nueva incidencia.

Contenido del playbook.


- name: Crear una nueva incidencia
hosts: localhost
tasks:
- name: Crear incidencia
jira:
uri: https://libroansible.atlassian.net/
username: alberto@oforte.net

© Alfaomega-RC Libros 241


ANSIBLE

password: FEyrVMmHGL
project: EJ
operation: create
summary: Crear incidencia
description: Incidencia creada desde Ansible
issuetype: Task
Comprobación de la creación de la incidencia.

MÓDULO LETSENCRYPT

En el siguiente ejemplo se crea un certificado web para libroansible.oforte.net,


previamente se generó el CSR y la clave SSL.

Contenido del playbook.


- name: Crear certificado para libroansible.oforte.net
hosts: servidor
gather_facts: False
tasks:
- name: Solicitar la petición
letsencrypt:
account_email: alberto@oforte.net
agreement: https://letsencrypt.org/documents/LE-SA-v1.2-November-
15-2017.pdf
account_key: /root/ssl/letsencrypt.key
csr: /root/ssl/libroansible.oforte.net.csr

242 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

dest: /root/ssl/libroansible.oforte.net.crt
register: peticion

- name: Crear directorio


file:
path: /var/www/libroansible/.well-known/acme-challenge/
state: directory
owner: www-data
group: www-data

- name: Generar el fichero necesario


copy:
dest: /var/www/libroansible/{{
peticion['challenge_data']['libroansible.oforte.net']['http-
01']['resource'] }}
content: "{{
peticion['challenge_data']['libroansible.oforte.net']['http-
01']['resource_value'] }}"

- name: Generar el certificado


letsencrypt:
account_email: alberto@oforte.net
agreement: https://letsencrypt.org/documents/LE-SA-v1.2-November-
15-2017.pdf
account_key: /root/ssl/letsencrypt.key
csr: /root/ssl/libroansible.oforte.net.csr
dest: /root/ssl/libroansible.oforte.net.crt
data: "{{ peticion }}"

Comprobación del certificado.


# openssl x509 -in libroansible.oforte.net.crt -text –noout
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
fa:5a:3c:af:c3:2f:2c:62:d3:97:b2:da:9b:cb:61:2a:d6:66
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN=Fake LE Intermediate X1
Validity
Not Before: Mar 30 14:32:14 2018 GMT
Not After : Jun 28 14:32:14 2018 GMT
Subject: CN=libroansible.oforte.net
[..]
Authority Information Access:
OCSP - URI:http://ocsp.stg-int-x1.letsencrypt.org

© Alfaomega-RC Libros 243


ANSIBLE

CA Issuers - URI:http://cert.stg-int-x1.letsencrypt.org/
X509v3 Subject Alternative Name:
DNS:libroansible.oforte.net
[..]

MÓDULO SUPERVISORCTL

En el siguiente ejemplo se detiene un servicio previamente iniciado.

Estado previo a ejecutar el playbook.


# supervisorctl status
long_script RUNNING pid 22460, uptime 0:00:05
Contenido del playbook.
- name: Detener servicio de supervisord
hosts: servidor
tasks:
- supervisorctl:
name: long_script
state: stopped
Estado posterior a ejecutar el playbook.
# supervisorctl status
long_script STOPPED Mar 30 05:45 PM

MÓDULOS CLOUD

Existen una gran cantidad de módulos para administrar distintos proveedores


de Cloud. Las plataformas con módulos para realizar diferentes tareas son:

Amazon (EC2, S3, AMI, ELB, lambda…)


Atomic (Container, host, image)
Azure (ACS, DNS, Load Balancer, VMs…)
Centurylink (Server, LB, Firewall, Alerts…)
Cloudscale (Server, Floating IP)
Cloudstack (Instancias, Redes, VPC, etc.)
Digital Ocean (Droplets, SSH key, Tags…)
Dimensiondata (VLAN, Network)
Docker (Imágenes, contenedores, etc.)

244 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

Google (GCE, Almacenamiento, Redes…)


Helm (Kubernetes)
Linode (instancias)
Lxc (Contenedores)
Lxd (Perfil, contenedores)
OpenStack (nova, keystone, security group…)
Ovh (Load Balancer)
Ovirt (Cluster, host, redes, VMS, etc.)
Packet (Dispositivo, SSH key)
Proxmox (KVM, template)
Profit Bricks (VMs, DC, Volúmenes)
Pubnub (Bloques)
Rackspace (CBS, CLB, MON, Network…)
Rhevm
Smartos (Imágenes, Máquinas virtuales)
Softlayer (Instancias virtuales)
Virt (VMs, redes, almacenamiento)
Vmware (Host, Guests, Templates…)
Vultr (Servidores, DNS, SSH key…)

La lista completa de módulos para la última versión de Ansible se encuentra en


la siguiente dirección:
http://docs.ansible.com/ansible/latest/modules/list_of_cloud_modules.html

En este libro se muestran ejemplos de algunos módulos para realizar distintas


tareas con proveedores de cloud.

AMAZON

Debido a la gran cantidad de módulos y opciones, en este apartado se


muestran ejemplos prácticos para realizar acciones comunes en AWS

Módulo EC2

En el siguiente ejemplo se crea una instancia en EC2 y se muestra su IP pública.

© Alfaomega-RC Libros 245


ANSIBLE

Contenido del playbook.


- name: Crear nueva instancia en AWS
hosts: localhost
gather_facts: False
tasks:
- name: Instalar librería boto
pip:
name: boto
state: latest
- name: Crear instancia
ec2:
aws_access_key: AKIAJW35G62O45YATHMA
aws_secret_key: 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
key_name: agonzalez
region: eu-west-1
instance_type: t2.micro
image: ami-8d0fb5fe # ID de debian 8
wait: true
exact_count: 1
vpc_subnet_id: subnet-f7cecaac
count_tag:
Name: libroansible
instance_tags:
Name: libroansible
register: ec2
- debug: msg="IP Pub.{{ec2.tagged_instances[0].public_ip}}"
Mensaje mostrado en debug y comprobación.
TASK [debug] **********
ok: [localhost] => {
"msg": "IP Publica 34.245.175.73"
}

246 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

Módulo EC2_KEY

En el siguiente ejemplo se crea una clave utilizando el valor de la clave pública


alojada en el servidor.

Contenido del playbook.


- name: Añadir clave pública a AWS
hosts: localhost
gather_facts: False
tasks:
- name: Instalar librería boto
pip:
name: boto
state: latest

- name: Leer clave pública del usuario actual


command: cat ~/.ssh/id_rsa.pub
register: miclave

- name: Añadir la clave


ec2_key:
aws_access_key: AKIAJW35G62O45YATHMA
aws_secret_key: sumvlXVT5gCwjsY6UY32wY6W2p1uVQM6z
name: ansible-clave
region: eu-west-1
key_material: "{{ miclave.stdout }}"

Comprobación de que la clave ha sido añadida.

Módulo EC2_GROUP
En el siguiente ejemplo se crea un security group para permitir el acceso web
(puertos 80 y 443).

© Alfaomega-RC Libros 247


ANSIBLE

Contenido del playbook.


- name: Crear un security group
hosts: localhost
gather_facts: False
tasks:
- name: Instalar librería boto3
pip:
name: boto3
state: latest

- name: Crear el SG permitir acceso web


ec2_group:
aws_access_key: AKIAJW35G62O45YATHMA
aws_secret_key: sumvlXVT5gBae6UY32wY6W2p1uVQM6z
name: ansible-sg
region: eu-west-1
description: Creado desde Ansible
vpc_id: vpc-26c26f40
rules:
- proto: tcp
ports:
- 80
- 443
cidr_ip: 0.0.0.0/0

Comprobación del security group creado.

248 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

Módulo EC2_SUBNET

En el siguiente ejemplo se crea una nueva subnet dentro del VPC indicado.

Contenido del playbook.


- name: Crear una subnet
hosts: localhost
gather_facts: False
tasks:
- name: Instalar librerías boto y boto3
pip:
name: boto3
state: latest
with_items:
- boto
- boto3

- name: Crear una subnet


ec2_vpc_subnet:
aws_access_key: AKIAJW35G62O45YATHMA
aws_secret_key: sumvlXVT5gBae9RTeUY32wY6W2p1uVQM6z
region: eu-west-1
vpc_id: vpc-26c26f40
cidr: 172.31.128.0/20
tags:
Name: Ansible Subnet
Comprobación de la creación de la subnet.

© Alfaomega-RC Libros 249


ANSIBLE

Módulo EC2_VOL
En el siguiente ejemplo se añade un nuevo disco a una instancia.
Contenido del playbook.
- name: Crear y asignar disco a una instancia
hosts: localhost
gather_facts: False
tasks:
- name: Instalar librería boto
pip:
name: boto
state: latest

- name: Crear volumen y asociarlo


ec2_vol:
aws_access_key: AKIAJW35G62O45YATHMA
aws_secret_key: sumvlXVT5gBae9RTeCwj32wY6W2p1uVQM6z
instance: i-026645caa9512f524
volume_size: 5
device_name: xvdb
region: eu-west-1
tags:
Name: Disco añadido por Ansible

Comprobación del disco añadido.

250 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

Módulo IAM

En el siguiente ejemplo se crea un grupo y usuarios asignados a él.

Contenido del playbook.


- name: Crear grupo y nuevos usuarios en IAM
hosts: localhost
gather_facts: False
tasks:
- name: Instalar librería boto
pip:
name: boto
state: latest

- name: Crear grupo


iam:
aws_access_key: AKIAJW35G62O45YATHMA
aws_secret_key: sumvlXVT5gBae9RTsY6UY32wY6W2p1uVQM6z
iam_type: group
name: "ansible-grupo"
state: present

- name: Crear usuarios


iam:
aws_access_key: AKIAJW35G62O45YATHMA
aws_secret_key: sumvlXVTeCwjsY6UY32wY6W2p1uVQM6z
iam_type: user
name: "{{ item }}"
groups: "ansible-grupo"
state: present
password: "changemeNOW!"
access_key_state: create
with_items:
- libroansible1
- libroansible2

Comprobación del grupo creado y los usuarios


(ver la imagen de la página siguiente)

© Alfaomega-RC Libros 251


ANSIBLE

AZURE

Debido a la gran cantidad de módulos y opciones, en este apartado se


muestran ejemplos prácticos para realizar acciones comunes en Azure.

252 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

Módulo AZURE_RM_RESOURCEGROUP

En el siguiente ejemplo se crea un Resource Group para ser utilizado en los


distintos ejemplos.

Contenido del playbook.


- name: Crear Resource Group
hosts: localhost
gather_facts: False
tasks:
- name: Instalar librerías necesarias
pip:
name: "{{ item }}"
state: present
with_items:
- azure==2.0.0
- packaging
- azure-mgmt-compute==2.0.0
- azure-mgmt-network==1.7.1
- azure-mgmt-storage==1.5.0

- name: Crear Resource Group


azure_rm_resourcegroup:
subscription_id: a899ede1-dda8-4e88-9305-362a5fdd8775
client_id: bedd86e3-ef1e-4a8d-b779-c23dd27230f9
secret: "+3PAbVbGWyVbxeW7X8N0ynjJKexD88VTcLCc9X3SI="
tenant: 0f57d21c-8c9a-415e-84d9-e0f0742070d2
name: AnsibleRG2
location: northeurope
state: present
Comprobación de la creación.

© Alfaomega-RC Libros 253


ANSIBLE

Módulo AZURE_RM_MANAGED_DISK

En el siguiente ejemplo se muestra cómo crear un disco dentro de Azure.

Contenido del playbook.


- name: Crear Resource Group
hosts: localhost
gather_facts: False
tasks:
- name: Instalar librerías necesarias
pip:
name: "{{ item }}"
state: present
with_items:
- azure==2.0.0
- packaging
- azure-mgmt-compute==2.0.0
- azure-mgmt-network==1.7.1
- azure-mgmt-storage==1.5.0

- name: Crear Resource Group


azure_rm_resourcegroup:
subscription_id: a899ede1-dda8-4e88-9305-362a5fdd8775
client_id: bedd86e3-ef1e-4a8d-b779-c23dd27230f9
secret: "+3PAbVbGWyVbxe0ynjJKexD88VTcLCc9X3SI="
tenant: 0f57d21c-8c9a-415e-84d9-e0f0742070d2
name: AnsibleRG2
location: northeurope
state: present

Comprobación de disco creado. (Ver la imagen de la página


siguiente)

254 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

Módulo AZURE_RM_NETWORK

En el siguiente ejemplo se crea una red dentro del Resource Group creado
anteriormente.

Contenido del playbook.


- name: Crear Resource Group
hosts: localhost
gather_facts: False
tasks:
- name: Instalar librerías necesarias
pip:
name: "{{ item }}"
state: present
with_items:
- azure==2.0.0
- packaging
- azure-mgmt-compute==2.0.0
- azure-mgmt-network==1.7.1
- azure-mgmt-storage==1.5.0

© Alfaomega-RC Libros 255


ANSIBLE

- name: Crear Resource Group


azure_rm_resourcegroup:
subscription_id: a899ede1-dda8-4e88-9305-362a5fdd8775
client_id: bedd86e3-ef1e-4a8d-b779-c23dd27230f9
secret: "+3PAbVbGWyVbxeW7X8XynjJKexD88VTcLCc9X3SI="
tenant: 0f57d21c-8c9a-415e-84d9-e0f0742070d2
name: AnsibleRG2
location: northeurope
state: present
Comprobación de la creación de la red.

Módulo AZURE_RM_SECURITYGROUP

En el siguiente ejemplo se crea un security group para permitir el tráfico web.

Contenido del playbook.


- name: Crear Resource Group
hosts: localhost
gather_facts: False
tasks:
- name: Instalar librerías necesarias
pip:
name: "{{ item }}"
state: present
with_items:
- azure==2.0.0
- packaging
- azure-mgmt-compute==2.0.0
- azure-mgmt-network==1.7.1
- azure-mgmt-storage==1.5.0

- name: Crear Resource Group

256 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

azure_rm_resourcegroup:
subscription_id: a899ede1-dda8-4e88-9305-362a5fdd8775
client_id: bedd86e3-ef1e-4a8d-b779-c23dd27230f9
secret:
"+3PAbVbGWyVbxeW7X8X8N0ynjJKexD88VTcLCc9X3SI="
tenant: 0f57d21c-8c9a-415e-84d9-e0f0742070d2
name: AnsibleRG2
location: northeurope
state: present
Comprobación del SG creado.

Módulo AZURE_RM_VIRTUALMACHINE

En este ejemplo se crea una máquina virtual con la distribución Debian 9.

Contenido del playbook.


- name: Crear máquina virtual
hosts: localhost
gather_facts: False
tasks:

© Alfaomega-RC Libros 257


ANSIBLE

- name: Instalar librerías necesarias


pip:
name: "{{ item }}"
state: present
with_items:
- azure==2.0.0
- packaging
- azure-mgmt-compute==2.0.0
- azure-mgmt-network==1.7.1
- azure-mgmt-storage==1.5.0

- name: Crear VM con Debian


azure_rm_virtualmachine:
subscription_id: a899ede1-dda8-4e88-9305-362a5fdd8775
client_id: bedd86e3-ef1e-4a8d-b779-c23dd27230f9
secret: "bxeW7X8X8N0ynjJKexD88VTcLCc9X3SI="
tenant: 0f57d21c-8c9a-415e-84d9-e0f0742070d2
virtual_network_name: ansible-network
vm_size: Standard_A0
resource_group: AnsibleRG
name: ansible01
admin_username: ansible
admin_password: l1br04ns1bl3$
image: # Obtenido desde https://wiki.debian.org/Cloud/MicrosoftAzure
offer: Debian
publisher: credativ
sku: 9
version: latest
Comprobación de la máquina virtual creada.

258 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

DIGITALOCEAN

La lista completa de módulos disponibles para DigitalOcean se muestra a


continuación:

digital_ocean Administra droplets/claves SSH.


Crea/elimina bloques de
digital_ocean_block_storage almacenamiento.
digital_ocean_domain Administra DNS.
digital_ocean_floating_ip Administra floating IPs.
digital_ocean_sshkey Administra claves SSH.
digital_ocean_tag Gestiona etiquetas.

Módulo DIGITAL_OCEAN

En el siguiente ejemplo se crea un doplet con la distribución Debian dentro de


la zona Frankfurt.

Contenido del playbook.


- name: Crear un nuevo Droplet con Debian
hosts: localhost
gather_facts: False
tasks:
- name: Instalar librería dopy
pip:
name: dopy
state: latest

- name: Crear droplet


digital_ocean:
state: present
command: droplet
name: ansible01
api_token: cfc71eb22f747ef6d3687d177727aa31eed0a
size_id: 2gb
region_id: fra1
image_id: debian-9-x64
wait_timeout: 500
register: mi_droplet

© Alfaomega-RC Libros 259


ANSIBLE

- debug:
msg: "Direccion IP es {{ mi_droplet.droplet.ip_address }}"
Mensaje mostrado por el módulo debug.
TASK [debug] **********
ok: [localhost] => {
"msg": "Direccion IP es 159.89.8.164"
}
Comprobación de la creación del droplet.

Módulo DIGITAL_OCEAN_BLOCK_STORAGE

En el siguiente ejemplo se crea un disco y se asigna al droplet creado


anteriormente.

Contenido del playbook.


- name: Crear nuevo disco
hosts: localhost
gather_facts: False
tasks:
- name: Instalar librería dopy
pip:
name: dopy
state: latest
- name: Crear disco
digital_ocean_block_storage:
state: present
command: create
volume_name: ansible-disco
api_token: cfc71eb22f747ef6d3687d177727aa31eed0a

260 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

block_size: 10
region: fra1
- name: Asignar disco
digital_ocean_block_storage:
state: present
command: attach
volume_name: ansible-disco
droplet_id: 87913141
api_token: cfc71eb22f747ef6d3687d177727aa31eed0a
region: fra1
Comprobación del volumen creado.

Módulo DIGITAL_OCEAN_FLOATING_IP

En el siguiente ejemplo se asocia una Floating IP (IP Flotante) al droplet creado


previamente y se visualiza la IP asignada.
Contenido del playbook.
- name: Asignar Floating IP
hosts: localhost
gather_facts: False
tasks:
- name: Asignar Floating IP
digital_ocean_floating_ip:
oauth_token: 2b85cfc71eb22f747ef6d3687d177727aa31eed0a
state: present
droplet_id: 87913141
register: ip_asig
- debug: msg="Floating IP asignada {{ ip_asig.data.floating_ip.ip }}"

© Alfaomega-RC Libros 261


ANSIBLE

Mensaje mostrado por el módulo debug.


TASK [debug] **********
ok: [localhost] => {
"msg": "Floating IP asignada 138.68.124.20"
}
Comprobación de la creación y asignación de la Floating IP.

Módulo DIGITAL_OCEAN_SSHKEY
En el siguiente ejemplo se añade una clave pública SSH a la cuenta asociada.

Contenido del playbook.


- name: Añadir clave pública ssh
hosts: localhost
gather_facts: False
tasks:
- name: Obtener clave del usuario
command: cat ~/.ssh/id_rsa.pub
register: miclave

- name: Añadir clave ssh


digital_ocean_sshkey:
oauth_token: cfc71eb22f747ef6d3687d177727aa31eed0a
state: present
name: "Clave SSH Alberto"
ssh_pub_key: "{{ miclave.stdout }}"
Comprobación de la clave añadida.

262 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

Módulo DIGITAL_OCEAN_TAG

En el siguiente ejemplo se etiqueta un droplet.

Contenido del playbook.


- name: Asignar etiqueta al droplet
hosts: localhost
gather_facts: False
tasks:
- name: Asignar etiqueta
digital_ocean_tag:
api_token: cfc71eb22f747ef6d3687d177727aa31eed0a
state: present
name: ansible-etiqueta
resource_id: "87913141"
Comprobación de la asignación de la etiqueta.

DOCKER

La lista de módulos disponibles para Docker se muestra a continuación:

docker_container Gestiona contenedores.


docker_image Gestiona imágenes.
docker_image_facts Inspecciona imágenes.
docker_login Se autentifica a Docker Registry.
docker_network Gestiona redes.
docker_secret Gestiona secretos de Docker.
docker_service Gestiona servicios y contenedores.
docker_volume Gestiona volúmenes.

© Alfaomega-RC Libros 263


ANSIBLE

Módulo DOCKER_CONTAINER
Este módulo contiene en total 80 opciones, la lista completa se detalla en la
siguiente dirección:
https://docs.ansible.com/ansible/2.4/docker_container_module.html

En el siguiente ejemplo creamos un contenedor que será accesible a través del


puerto 9080, además montaremos un directorio desde el servidor Docker dentro
del contenedor.

Contenido del playbook.


- name: Crear un contenedor y montar un directorio
hosts: servidor
tasks:
- name: Crear directorio
file:
name: "{{ item }}"
state: directory
owner: www-data
group: www-data
with_items:
- "/contenedores"
- "/contenedores/web"
- name: Crear index.html
copy:
dest: /contenedores/web/index.html
content: "index.html creado con Ansible"
owner: www-data
group: www-data
- pip:
name: docker-py
state: latest

- name: Crear contenedor


docker_container:
name: ansible-web
image: httpd
pull: true
state: started
volumes:
- /contenedores/web:/usr/local/apache2/htdocs
ports:
- "9080:80"

264 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

Comprobación de la creación del contenedor.


# docker ps -f name=ansible-web
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d4cae2f44a40 httpd "httpd-foreground" About a minute ago Up About a minute
0.0.0.0:9080->80/tcp ansible-web
# curl http://localhost:9080
index.html creado con Ansible
# docker inspect ansible-web -f "{{ .Mounts }}"
[{bind /contenedores/web /usr/local/apache2/htdocs rw true }]

Módulo DOCKER_IMAGE
En los siguientes ejemplos se hacen tareas comunes con imágenes (descargar,
publicar).

Contenido del playbook.


- name: Tareas con imágenes
hosts: servidor
tasks:
- pip:
name: docker-py
state: latest

- name: Descargar imagen CentOS


docker_image:
name: centos:latest
state: present

- name: Guardar imagen en repositorio local


docker_image:
name: centos:latest
repository: localhost:5000/centos
push: true
tag: latest

- name: Guardar imagen en un fichero


docker_image:
name: localhost:5000/centos
tag: latest
archive_path: /contenedores/centos.tar

Comprobación de las tareas.


# docker images | grep centos

© Alfaomega-RC Libros 265


ANSIBLE

centos latest 2d194b392dd1 3 weeks ago 195MB


localhost:5000/centos latest 2d194b392dd1 3 weeks ago 195MB
# ls -lhtr /contenedores/centos.tar
-rw-r--r-- 1 root root 195M Mar 31 18:51 /contenedores/centos.tar

Módulo DOCKER_LOGIN
En el siguiente ejemplo se autentica en Docker Hub y se sube una imagen a él.
Contenido del playbook.
- name: Hacer login en Docker Registry
hosts: servidor
tasks:
- pip:
name: docker-py
state: latest

- name: Autenticar
docker_login:
email: alberto@oforte.net
username: libroansible
password: l1br04ns1bl3
state: present

- name: Publicar imagen


docker_image:
name: centos
repository: libroansible/centos:7.4
tag: latest
Comprobación de la publicación de la imagen en Docker Hub.

266 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

Módulo DOCKER_NETWORK

En el siguiente ejemplo se añade una red y se conecta el contenedor creado


previamente.

Contenido del playbook.


- name: Crear red y conectar ansible-web
hosts: servidor
tasks:
- pip:
name: docker-py
state: latest

- name: Crear red llamada ansible


docker_network:
name: ansible
state: present
connected:
- ansible-web
Comprobación de la creación de la red y conexión del
contenedor.
# docker network ls -f name=ansible
NETWORK ID NAME DRIVER SCOPE
ba366c53163b ansible bridge local
# docker network inspect ansible -f "{{ .Containers }}"
map[d4cae2f44a402c21fb1e155329072252ebe1181bc8086871b414fc590c5ac167:{ansib
le-web 1bcf2e33e635fd542bcd3a619e978fcbbbf7008cfdb363d0e7c9785f357ba4b5
02:42:ac:12:00:02 172.18.0.2/16 }]

Módulo DOCKER_VOLUME

En el siguiente ejemplo se crea un volumen a ser utilizado por los


contenedores.

Contenido del playbook.


- name: Crear volumen
hosts: servidor
tasks:
- pip:
name: docker-py

© Alfaomega-RC Libros 267


ANSIBLE

state: latest

- name: Crear volumen


docker_volume:
name: ansible-volumen
state: present
Comprobación del volumen creado.
# docker volume ls -f name=ansible-volumen
DRIVER VOLUME NAME
local ansible-volumen

GOOGLE

Debido a la gran cantidad de módulos y opciones, en este apartado se


muestran ejemplos prácticos para realizar acciones comunes en GCP.

Módulo GCE

En el siguiente ejemplo se crea una instancia dentro de Google Cloud Platform.

Contenido del playbook.


- name: Asignar etiquetas a la instancia ansible01
hosts: localhost
gather_facts: False
vars:
proyecto: oforte-196215
zona: europe-west3-c
instancia: ansible01
tasks:
- name: Instalar librerías necesarias
pip:
name: "{{ item }}"
state: latest
with_items:
- apache-libcloud
- credentials
- google-api-python-client
- google-auth
- google-auth-httplib2
- name: Asignar etiquetas
gce_labels:
service_account_email: "ansible@oforte-196215..."

268 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

credentials_file: "/root/{{ proyecto }}.json"


project_id: "{{ proyecto }}"
labels:
entorno: ejemplo
creado_por: ansible
resource_url: https://www.googleapis.com/compute/beta/projects/{{
proyecto }}/zones/{{ zona }}/instances/{{ instancia }}
state: present
Comprobación de la creación de la instancia.

Módulo GCE_LABELS

En el siguiente ejemplo se establecen etiquetas a la instancia creada


previamente.

Contenido del playbook.


- name: Asignar etiquetas a la instancia ansible01
hosts: localhost
gather_facts: False
vars:
proyecto: oforte-196215
zona: europe-west3-c
instancia: ansible01
tasks:
- name: Instalar librerías necesarias
pip:
name: "{{ item }}"
state: latest
with_items:
- apache-libcloud
- credentials
- google-api-python-client
- google-auth
- google-auth-httplib2
- name: Asignar etiquetas
gce_labels:
service_account_email: "ansible@oforte-196215.. "
credentials_file: "/root/{{ proyecto }}.json"

© Alfaomega-RC Libros 269


ANSIBLE

project_id: "{{ proyecto }}"


labels:
entorno: ejemplo
creado_por: ansible
resource_url:
https://www.googleapis.com/compute/beta/projects/{{
proyecto }}/zones/{{ zona }}/instances/{{ instancia }}
state: present
Comprobación de las etiquetas asignadas.

Módulo GCE_NET

En el siguiente ejemplo se crean una red y una subred personalizada. Además,


se crea una regla de firewall.
Contenido del playbook.
- name: Crear instancia en GCP
hosts: localhost
gather_facts: False
tasks:
- name: Instalar librerías necesarias
pip:
name: "{{ item }}"
state: latest

270 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

with_items:
- apache-libcloud
- credentials
- name: Crear red y subnet
gce_net:
service_account_email: "ansible@oforte-196215."
credentials_file: "/root/oforte.pem"
project_id: oforte-196215
name: ansible-red
mode: custom
subnet_name: "ansible-subred"
subnet_region: europe-west3
ipv4_range: '192.168.10.0/24'
state: "present"
- name: Crear regla de firewall
gce_net:
service_account_email: "ansible@oforte-196215.."
credentials_file: "/root/oforte.pem"
project_id: oforte-196215
name: default
fwname: "ansible-fw-regla"
allowed: tcp:8040
state: "present"
src_tags: "ansible-regla"
Comprobación de la creación de la red subred.

© Alfaomega-RC Libros 271


ANSIBLE

Comprobación de creación de la regla de firewall.

Módulo GCE_PD

En el siguiente ejemplo se crea un disco y se asigna a la instancia creada


anteriormente.

Contenido del playbook.


- name: Crear disco en GCP y asociarlo
hosts: localhost
gather_facts: False
tasks:
- name: Instalar librerías necesarias
pip:
name: "{{ item }}"
state: latest
with_items:
- apache-libcloud

272 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

- credentials
- name: Crear disco y asociar
gce_pd:
service_account_email: "ansible@oforte-196215.."
credentials_file: "/root/oforte-196215.json"
project_id: oforte-196215
name: ansible-disco
instance_name: ansible01
zone: europe-west3-c
size_gb: 20
state: present
mode: READ_WRITE
Comprobación de la creación y asociación.

Módulo GCE_TAG

En el siguiente ejemplo se hacen las etiquetas http-server y https-server para


permitir el acceso a través del firewall.
Contenido del playbook.
- name: Habilitar HTTP y HTTPS asignando tags
hosts: localhost
gather_facts: False
tasks:
- name: Instalar librerías necesarias
pip:
name: "{{ item }}"
state: latest
with_items:
- apache-libcloud
- credentials
- name: Asignar tags
gce_tag:
service_account_email: "ansible@oforte-196215.."
pem_file: "/root/oforte-196215.json"
project_id: oforte-196215
instance_name: ansible01
zone: europe-west3-c
tags: http-server,https-server

© Alfaomega-RC Libros 273


ANSIBLE

Comprobación de las etiquetas asignadas.

LIBVIRT

La lista completa de módulos disponibles para administrar libvirt se muestra a


continuación:

virt Administra máquinas virtuales.


virt_net Administra configuración de redes.
virt_pool Administra pool de almacenamiento.

Módulo VIRT

En el siguiente ejemplo primero se obtiene la lista de máquinas virtuales, para


después obtener el estado y posteriormente mostrarlo.

Contenido del playbook.


- name: Listar las VMs en libvirt y obtener estado
hosts: servidor
tasks:
- name: Listar VMs
virt:
command: list_vms
register: vms
- name: Obtener información de las VMS
virt:
command: status
name: "{{ item }}"
register: estados
with_items: "{{ vms.list_vms }}"

274 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

- debug: msg="VM {{ item.item }} estado {{ item.status }}"


with_items: "{{ estados.results }}" Salida del playbook.
Resultado de la ejecución.
PLAY [Listar las VMs en libvirt y obtener estado] ********
TASK [Gathering Facts] **
ok: [localhost]
TASK [Listar VMs] *****
TASK [Obtener información de las VMS] ***
ok: [localhost] => (item=debian8)
ok: [localhost] => (item=win2k8r2)
TASK [debug] **********
ok: [localhost] => (item=None) => {
"msg": "VM debian8 estado shutdown"
}
ok: [localhost] => (item=None) => {
"msg": "VM win2k8r2 estado shutdown"
}

PLAY RECAP **********


localhost : ok=4 changed=0 unreachable=0 failed=0

Módulo VIRT_NET

En el siguiente ejemplo se crea una red dentro de libvirt.

Contenido del playbook.


- name: Crear red, listar las redes en libvirt y obtener estado
hosts: servidor
tasks:
- name: Definir red
virt_net:
command: define
name: red_ansible
xml: >
<network>
<name>red_ansible</name>
<forward mode='nat'/>
<bridge name='virbr2' stp='on' delay='0'/>
<mac address='52:54:00:3a:7e:57'/>
<ip address='192.168.12.1' netmask='255.255.255.0'>
<dhcp>
<range start='192.168.12.2' end='192.168.12.254'/>

© Alfaomega-RC Libros 275


ANSIBLE

</dhcp>
</ip>
</network>

- name: Crear red


virt_net:
command: create
name: red_ansible

Comprobación de la creación de la red.


# virsh net-info red_ansible
Name: red_ansible
UUID: 75bf1aca-d07c-4f20-a9cf-2da25d25d9fc
Active: yes
Persistent: yes
Autostart: no
Bridge: virbr2

Módulo VIRT_POOL

En el siguiente ejemplo se crea un almacenamiento local.

Contenido del playbook.


- name: Crear almacenamiento
hosts: servidor
tasks:
- name: Definir almacenamiento
virt_pool:
command: define
name: almacenamiento_ansible
xml: >
<pool type='dir'>
<name>almacenamiento_ansible</name>
<source>
</source>
<target>
<path>/almacenamiento/</path>
<permissions>
<mode>0755</mode>
<owner>110312</owner>
<group>110312</group>
</permissions>
</target>

276 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

</pool>
- name: Crear almacenamiento
virt_pool:
command: create
name: almacenamiento_ansible
Comprobación de la creación del almacenamiento.
# virsh pool-info almacenamiento_ansible
Name: almacenamiento_ansible
UUID: 782d767e-9dfc-48e0-828e-c94f5f747587
State: running
Persistent: yes
Autostart: no
Capacity: 28.71 GiB
Allocation: 22.22 GiB
Available: 6.49 GiB

OPENSTACK

Debido a la gran cantidad de módulos y opciones, en este apartado se


muestran ejemplos prácticos para realizar acciones comunes en OpenStack:

Módulo OS_PROJECT

En el siguiente ejemplo se crea un proyecto llamado ansible para ser utilizado


posteriormente por los otros módulos.

Contenido del playbook.


- name: Crear proyecto
hosts: localhost
gather_facts: False
vars:
autenticar:
auth_url: "https://openstack.oforte.net:13000/v3/"
username: "admin"
password: "keJGVNbbA9QrnXXZqwCevPUmA"
domain_name: default
user_domain_name: default
project_domain_name: default
project_name: admin
environment:
OS_IDENTITY_API_VERSION: 3

© Alfaomega-RC Libros 277


ANSIBLE

tasks:
- name: Instalar librería necesaria
pip:
name: shade
state: latest
- name: Crear proyecto ansible
os_project:
auth: "{{ autenticar }}"
name: ansible
description: Creado por Ansible
domain_id: default
validate_certs: False
Comprobación de la creación.
$ openstack project show ansible -f yaml
description: Creado por Ansible
enabled: true
id: d65ed18f8e2e4fa585f8410a76c146d6
name: ansible

Módulo OS_NETWORK

En el siguiente ejemplo se crea una red dentro del proyecto creado


previamente.

Contenido del playbook.


- name: Crear red dentro del proyecto ansible
hosts: localhost
gather_facts: False
environment:
OS_IDENTITY_API_VERSION: 3
tasks:
- name: Incluir variables para autenticar
include_vars: autenticar.yml

- name: Instalar librería necesaria


pip:
name: shade
state: latest
- name: Crear red ansible-red en el proyecto ansible
os_network:
auth: "{{ autenticar }}"
project: ansible

278 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

name: ansible-red
state: present
external: False
validate_certs: False
Comprobación de la creación.
$ openstack network list --project ansible -f yaml
- ID: edd02b43-ff7f-413d-bd0b-a7daaf64ae81
Name: ansible-red
Subnets: ''

Módulo OS_SUBNET

En el siguiente ejemplo se crea una subred dentro de la red creada


previamente.

Contenido del playbook.


- name: Crear subred dentro de la red ansible-red
hosts: localhost
gather_facts: False
environment:
OS_IDENTITY_API_VERSION: 3
tasks:
- name: Incluir variables para autenticar
include_vars: autenticar.yml

- name: Instalar librería necesaria


pip:
name: shade
state: latest
- name: Crear ansible-subred en la red ansible-red
os_subnet:
auth: "{{ autenticar }}"
project: ansible
network_name: ansible-red
name: ansible-subred
state: present
cidr: 192.168.22.0/24
dns_nameservers:
- 8.8.4.4
- 8.8.8.8
validate_certs: False

© Alfaomega-RC Libros 279


ANSIBLE

Comprobación de la creación de la subred.

Módulo OS_ROUTER
En el siguiente ejemplo se conecta la subred ansible-subred con la red pública
para poder acceder a la instancia que crearemos a través de una IP flotante
(Floating IP).
Contenido del playbook.
- name: Crear un router que conecte ansible-subnet al ext.
hosts: localhost
gather_facts: False
environment:
OS_IDENTITY_API_VERSION: 3
tasks:
- name: Incluir variables para autenticar
include_vars: autenticar.yml

- name: Instalar librería necesaria


pip:
name: shade
state: latest
- name: Crear el router
os_router:
auth: "{{ autenticar }}"
project: ansible
name: ansible-router

280 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

state: present
network: services
interfaces:
- ansible-subred
validate_certs: False
Comprobación del router y de las conexiones.

Módulo OS_SECURITY_GROUP

En el siguiente ejemplo se crea un security group a ser utilizado


posteriormente para crear reglas de firewall.

Contenido del playbook.


- name: Crear un security group para ser utilizado posteriormente
hosts: localhost

© Alfaomega-RC Libros 281


ANSIBLE

gather_facts: False
environment:
OS_IDENTITY_API_VERSION: 3
tasks:
- name: Incluir variables para autenticar
include_vars: autenticar.yml

- set_fact: # Definir el proyecto donde se creará


autenticar: "{{ autenticar|combine({'project_name':'ansible'}) }}"

- name: Instalar librería necesaria


pip:
name: shade
state: latest

- name: Crear el security group


os_security_group:
auth: "{{ autenticar }}"
name: ansible-sg
description: Creado por Ansible
state: present
validate_certs: False

Comprobación de la creación.
$ openstack security group list --project ansible -f yaml
- Description: Default security group
ID: 1b070218-db51-4025-8356-4b54735a3410
Name: default
Project: ''
- Description: Creado por Ansible
ID: 39412497-db33-49fe-bdb0-41b19e1eda38
Name: ansible-sg
Project: ''

Módulo OS_SECURITY_GROUP_RULE

En el siguiente ejemplo permitimos la conexión a los puertos 22 y 80 usando el


protocolo TCP.

Contenido del playbook.


- name: Permitir conexión SSH y HTTP
hosts: localhost
gather_facts: False

282 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

environment:
OS_IDENTITY_API_VERSION: 3
tasks:
- name: Incluir variables para autenticar
include_vars: autenticar.yml

- set_fact: # Definir el proyecto dónde se creará


autenticar: "{{
autenticar|combine({'project_name':'ansible'}) }}"

- name: Instalar librería necesaria


pip:
name: shade
state: latest

- name: Crear reglas de firewall


os_security_group_rule:
auth: "{{ autenticar }}"
security_group: ansible-sg
protocol: tcp
port_range_min: "{{ item }}"
port_range_max: "{{ item }}"
remote_ip_prefix: 0.0.0.0/0
state: present
validate_certs: False
with_items:
- 22
- 80
Comprobación de las reglas creadas.

© Alfaomega-RC Libros 283


ANSIBLE

Módulo OS_SERVER

En el siguiente ejemplo se crea un servidor utilizando los componentes creados


previamente (proyecto, red, subred, security group) usando una imagen existente.

Contenido del playbook.


- name: Crear un servidor en el proyecto ansible
hosts: localhost
gather_facts: False
environment:
OS_IDENTITY_API_VERSION: 3
tasks:
- name: Incluir variables para autenticar
include_vars: autenticar.yml

- set_fact: # Definir el proyecto donde se creará


autenticar: "{{
autenticar|combine({'project_name':'ansible'}) }}"

- name: Instalar librería necesaria


pip:
name: shade
state: latest
- name: Crear el servidor
os_server:
auth: "{{ autenticar }}"
name: ansible01
image: CirrOS
flavor: m1.tiny
security_groups:
- ansible-sg
nics:
- net-name: ansible-red
floating_ip_pools: "services"
validate_certs: False
Comprobación de la creación de la instancia.

284 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

$ ssh cirros@10.116.127.178 "ip a s eth0"


cirros@10.116.127.178's password:
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc
pfifo_fast qlen 1000
link/ether fa:16:3e:4e:ae:03 brd ff:ff:ff:ff:ff:ff
inet 192.168.22.13/24 brd 192.168.22.255 scope global eth0
inet6 fe80::f816:3eff:fe4e:ae03/64 scope link
valid_lft forever preferred_lft forever

MÓDULOS CLUSTERING
Estos módulos sirven para gestionar diferentes clusters.

Añade, modifica o elimina servicios dentro


consul de un cluster consul.
consul_acl Manipula claves ACL y reglas de consul.
Manipula entradas en el almacenamiento
consul_kv clave/valor de un cluster consul.
consul_session Manipula sesiones de consul.
kubernetes Administra recursos Kubernete.
oc Administra recursos OpenShift.
pacemaker_cluster Administra un cluster pacemaker.
Crea, elimina, obtiene y actualiza znodos
znode usando ZooKeeper.

© Alfaomega-RC Libros 285


ANSIBLE

MÓDULOS MONITORING
Estos módulos sirven para gestionar diferentes plataformas de monitorización.

Notifica airbrake sobre


airbrake_deployment implementaciones de aplicaciones.
Notifica a BigPanda sobre las
bigpanda implementaciones.
boundary_meter Administra contadores de límites.
circonus_annotation Crea una anotación en circonus.
Publica eventos en el servicio
datadog_event DataDog.
datadog_monitor Administra monitores Datadog.
Notifica a Honeybadger.io sobre
honeybadger_deployment implementaciones de aplicaciones.
icinga2_feature Administra la función Icinga2.
librato_annotation Crea una anotación en librato.
Módulo para rastrear registros a
logentries través de logentries.com.
Administra su cuenta de LogicMonitor
a través de libros de jugadas de
logicmonitor Ansible.
Recopila datos sobre objetos
logicmonitor_facts LogicMonitor.
logstash_plugin Administra complementos de Logstash.
Administra el estado de un programa
monit monitoreado a través de Monit.
Realiza tareas comunes en Nagios
relacionadas con el tiempo de
nagios inactividad y las notificaciones.
Notifica a newrelic sobre
newrelic_deployment implementaciones de aplicaciones.
Crea ventanas de mantenimiento de
pagerduty PagerDuty.
Desencadena, confirma o resuelve
pagerduty_alert incidentes de PagerDuty.

286 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

Pausa / no pausa las alertas de


pingdom Pingdom.
Notifica a Rollbar sobre
rollbar_deployment implementaciones de aplicaciones.
sensu_check Administra los cheques de Sensu.
Administra la configuración del
sensu_client cliente Sensu.
Administra la configuración del
sensu_handler controlador Sensu.
Administra las entradas de silencio
sensu_silence de Sensu.
sensu_subscription Administra suscripciones de Sensu.
Envía eventos de anotación y
stackdriver despliegue de código a stackdriver.
Crea ventanas de mantenimiento para
statusio_maintenance tu panel de estado.io.
Pausa e inicia Uptime Robot
uptimerobot Monitoring

ZABBIX

MÓDULO ZABBIX_GROUP

En el siguiente ejemplo se crea un grupo dentro de Zabbix.

Contenido del playbook.


- name: Crear grupo
hosts: localhost
gather_facts: False
tasks:
- pip: name=zabbix-api state=latest
- zabbix_group:
server_url: http://zabbix.oforte.net
login_user: ansible
login_password: Start123
state: present
host_groups:
- Ejemplo libro

© Alfaomega-RC Libros 287


ANSIBLE

Comprobación de la creación.

MÓDULO ZABBIX_HOST

En el siguiente ejemplo se crea un nuevo host dentro de Zabbix.

Contenido del playbook.


- name: Crear servidor
hosts: localhost
gather_facts: False
tasks:
- pip: name=zabbix-api state=latest
- zabbix_host:
server_url: http://zabbix.oforte.net
login_user: ansible
login_password: Start123
state: present
host_name: "libro.oforte.net"
host_groups: "Ejemplo libro"
interfaces:
- type: 1
main: 1
useip: 1
ip: 192.168.100.200
dns: ""
port: 10050

288 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

Comprobación de la creación.

MÓDULO ZABBIX_HOSTMACRO

En el siguiente ejemplo se crea un hostmacro dentro de Zabbix.

Contenido del playbook.


- name: Crear hostmacro
hosts: localhost
gather_facts: False
tasks:
- pip: name=zabbix-api state=latest
- zabbix_hostmacro:
server_url: http://zabbix.oforte.net
login_user: ansible
login_password: Start123
state: present
host_name: libro.oforte.net
macro_name: Lugar
macro_value: Frankfurt

© Alfaomega-RC Libros 289


ANSIBLE

Comprobación de la creación del hostmacro.

MÓDULO ZABBIX_MAINTENANCE

En el siguiente ejemplo se establece una ventana de mantenimiento al servidor


previamente creado.

Contenido del playbook.


- name: Establecer mantenimiento
hosts: localhost
gather_facts: False
tasks:
- pip: name=zabbix-api state=latest
- zabbix_maintenance:
server_url: http://zabbix.oforte.net
login_user: ansible
login_password: Start123
state: present
host_name: libro.oforte.net
name: Estableciendo mantenimiento desde Ansible
desc: Establecido desde Ansible
minutes: 30

290 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

Comprobación de la activación de la ventana de


mantenimiento.

MÓDULO ZABBIX_SCREEN

En el siguiente ejemplo se crea una pantalla (screen) en Zabbix mostrando la


carga del procesador y los usuarios conectados.

Contenido del playbook.


- name: Crear pantalla
hosts: localhost
gather_facts: False
tasks:
- pip: name=zabbix-api state=latest
- zabbix_screen:
server_url: http://zabbix.oforte.net
login_user: ansible
login_password: Start123
screens:
- screen_name: PantallaAnsible
host_group: Zabbix Servers
state: present
graph_names:
- CPU load
- Users connected
graph_width: 200
graph_height: 100

© Alfaomega-RC Libros 291


ANSIBLE

Comprobación de la pantalla creada.

MÓDULOS IDENTIDAD

Estos módulos sirven para gestionar diferentes plataformas de identificación.

CYBERARK

Los módulos disponibles son los siguientes:

cyberark_authentication Módulo para CyberArk Vault.


cyberark_user Módulo para administrar usuarios.

IPA

Los módulos disponibles son los siguientes:

ipa_dnsrecord Administra FreeIPA DNS records.


ipa_group Administra FreeIPA group.
ipa_hbacrule Administra FreeIPA HBAC rule.

292 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

ipa_host Administra FreeIPA host.


ipa_hostgroup Administra FreeIPA host groups.
ipa_role Administra FreeIPA role.
ipa_sudocmd Administra FreeIPA sudo command.
ipa_sudocmdgroup Administra FreeIPA sudo command group.
ipa_sudorule Administra FreeIPA sudo rule.
ipa_user Administra FreeIPA users.

MÓDULO IPA_DNSRECORD

En este ejemplo añadimos un registro dentro del servidor IPA en la zona DNS
indicada.

Contenido del playbook.


- name: Añadir registro DNS
hosts: servidoripa
gather_facts: False
tasks:
- ipa_dnsrecord:
ipa_host: libroansible.oforte.net
ipa_pass: l1br04ns1bl3
state: present
zone_name: libroansible.oforte.net
record_name: ansible01
record_type: 'A'
record_value: '192.168.22.100'
validate_certs: False
Comprobación del registro añadido.
# ipa dnsrecord-find libroansible.oforte.net ansible01
Record name: ansible01
A record: 192.168.22.100

MÓDULO IPA_GROUP

En el siguiente ejemplo se añade un grupo.

© Alfaomega-RC Libros 293


ANSIBLE

Contenido del playbook.


- name: Añadir grupo
hosts: servidoripa
gather_facts: False
tasks:
- ipa_group:
ipa_host: libroansible.oforte.net
ipa_pass: l1br04ns1bl3
state: present
cn: ansible-grupo
validate_certs: False
Comprobación de la creación del grupo.
# ipa group-find ansible-grupo
---------------
1 group matched
---------------
Group name: ansible-grupo
GID: 1775200001
----------------------------
Number of entries returned 1
----------------------------

MÓDULO IPA_HOST
En el siguiente ejemplo se registra un servidor en IPA.
Contenido del playbook.
- name: Añadir servidor
hosts: servidoripa
gather_facts: False
tasks:
- ipa_host:
ipa_host: libroansible.oforte.net
ipa_pass: l1br04ns1bl3
state: present
validate_certs: False
fqdn: ansible02.libroansible.oforte.net
description: Servidor creado por Ansible
ip_address: 192.168.33.101
Comprobación de la creación del host.
# ipa host-show ansible02.libroansible.oforte.net

294 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

Host name: ansible02.libroansible.oforte.net


Description: Servidor creado por Ansible
Principal name: host/ansible02.libroansible.oforte.net@LIBROANSIBLE.OFORTE.NET
Principal alias: host/ansible02.libroansible.oforte.net@LIBROANSIBLE.OFORTE.NET
Password: False
Keytab: False
Managed by: ansible02.libroansible.oforte.net

MÓDULO IPA_ROLE

En el siguiente ejemplo se crea un nuevo rol.


Contenido del playbook.
- name: Añadir rol
hosts: servidoripa
gather_facts: False
tasks:
- ipa_role:
ipa_host: libroansible.oforte.net
ipa_pass: l1br04ns1bl3
state: present
validate_certs: False
cn: Usuarios Ansible
description: Creado por Ansible
Comprobación de la creación del rol.
# ipa role-show "Usuarios Ansible"
Role name: Usuarios Ansible
Description: Creado por Ansible

MÓDULO IPA_USER

En el siguiente ejemplo se crea un usuario, se le asigna una clave SSH y se


asigna al grupo previamente creado.

Contenido del playbook.


- name: Crear usuario
hosts: servidoripa
gather_facts: False
tasks:
- name: Obtener clave del usuario
command: cat ~/.ssh/id_rsa.pub

© Alfaomega-RC Libros 295


ANSIBLE

register: miclave

- name: Crear usuario


ipa_user:
ipa_host: libroansible.oforte.net
ipa_pass: l1br04ns1bl3
state: present
uid: ansible-usuario
givenname: Alberto
sn: Gonzalez
mail:
- alberto@oforte.net
sshpubkey:
- "{{ miclave.stdout }}"
validate_certs: False

- name: Asignar grupo a usuario


ipa_group:
ipa_host: libroansible.oforte.net
ipa_pass: l1br04ns1bl3
state: present
cn: ansible-grupo
user:
- ansible-usuario
validate_certs: False
Comprobación del usuario creado.
# ipa role-show "Usuarios Ansible"
Role name: Usuarios Ansible
Description: Creado por Ansible
# ipa user-find ansible-usuario
--------------
1 user matched
--------------
User login: ansible-usuario
First name: Alberto
Last name: Gonzalez
Home directory: /home/ansible-usuario
Login shell: /bin/sh
Principal name: ansible-usuario@LIBROANSIBLE.OFORTE.NET
Principal alias: ansible-usuario@LIBROANSIBLE.OFORTE.NET
Email address: alberto@oforte.net
UID: 1775200003
GID: 1775200003

296 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

SSH public key fingerprint: SHA256:luTfVu+tzuxA (ssh-rsa)


Account disabled: False
----------------------------
Number of entries returned 1
----------------------------
# ipa group-show ansible-grupo
Group name: ansible-grupo
GID: 1775200001
Member users: ansible-usuario

Módulo OPENDJ

opendj_backendprop Actualizar configuración OpendJ.

MÓDULOS INVENTARIO
Estos módulos sirven para gestionar el inventario dentro de Ansible.

add_host Añade un nodo al inventario del playbook en


memoria.
group_by Crea un grupo de Ansible basado en facts.

MÓDULO ADD_HOST

En el siguiente ejemplo se crea un nuevo servidor en Digital Ocean, una vez


creado, se añade al inventario en memoria y posteriormente se conecta a él.

Contenido del playbook.


- name: Crear un nuevo Droplet con Debian
hosts: localhost
gather_facts: False
tasks:
- name: Instalar librería dopy
pip:
name: dopy
state: latest

- name: Obtener ID de la clave SSH

© Alfaomega-RC Libros 297


ANSIBLE

digital_ocean:
state: present
command: ssh
name: "Clave SSH Alberto"
api_token: cfc71eb22f747ef6d3687d177727aa31eed0a
register: clave_ssh

- name: Crear droplet


digital_ocean:
state: present
command: droplet
name: ansible01
api_token: cfc71eb22f747ef6d3687d177727aa31eed0a
size_id: 2gb
region_id: fra1
image_id: debian-9-x64
ssh_key_ids: "{{ clave_ssh.ssh_key.id }}"
wait_timeout: 500
register: mi_droplet
- debug:
msg: "La direccion IP es {{ mi_droplet.droplet.ip_address }}"
- add_host:
name: "{{ mi_droplet.droplet.ip_address }}"
groups: "recien_creado"
- name: Esperar que el servidor esté disponible
wait_for:
host: "{{ mi_droplet.droplet.ip_address }}"
port: 22

- name: Conectar al servidor recien creado


hosts: recien_creado
tasks:
- command: uname -a
register: uname
- debug: msg="{{ uname.stdout }}"

Salida del playbook.


PLAY [Crear un nuevo Droplet con Debian] ***
TASK [Instalar librería dopy] *****************
ok: [localhost]
TASK [Obtener ID de la clave SSH] *********
ok: [localhost]
TASK [Crear droplet] **
changed: [localhost]

298 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

TASK [debug] **********


ok: [localhost] => {
"msg": "La direccion IP es 207.154.230.84"
}
TASK [add_host] ******
changed: [localhost]
TASK [Esperar que el servidor esté disponible] ***********
ok: [localhost]
PLAY [Conectar al servidor recién creado] ****
TASK [Gathering Facts] **
ok: [207.154.230.84]
TASK [command] ******
changed: [207.154.230.84]
TASK [debug] **********
ok: [207.154.230.84] => {
"msg": "Linux ansible01 4.9.0-6-amd64 #1 SMP Debian
4.9.82-1+deb9u3 (2018-03-02) x86_64 GNU/Linux"
}

PLAY RECAP **********


207.154.230.84 : ok=3 changed=1 unreachable=0 failed=0
localhost : ok=6 changed=2 unreachable=0 failed=0

MÓDULO GROUP_BY

En el siguiente ejemplo se agrupan los servidores por su distribución en el


primer Play, en los dos restantes se conecta a los grupos generados para
comprobar la versión de la distribución por cada servidor.

Contenido del playbook.


- name: Agrupar servidores por distribución
hosts: all
remote_user: alberto
tasks:
- group_by:
key: "distro_{{ ansible_distribution }}"

- name: Conectar a los servidores CentOS


hosts: distro_CentOS
remote_user: alberto
gather_facts: False
tasks:

© Alfaomega-RC Libros 299


ANSIBLE

- command: cat /etc/centos-release


register: version
- debug: msg="{{ version.stdout }}"

- name: Conectar a los servidores Debian


hosts: distro_Debian
remote_user: alberto
gather_facts: False
tasks:
- command: cat /etc/debian_version
register: version
- debug: msg="{{ version.stdout }}"
Resultado del playbook.
PLAY [Agrupar servidores por distribución] ****
TASK [Gathering Facts] **
ok: [debian02]
ok: [ansible01]
ok: [debian01]
ok: [centos01]
ok: [centos02]
TASK [group_by] ******
ok: [centos02]
ok: [centos01]
ok: [debian02]
ok: [debian01]
ok: [ansible01]
PLAY [Conectar a los servidores CentOS] ****
TASK [command] ******
changed: [centos01]
changed: [centos02]
TASK [debug] **********
ok: [centos02] => {
"msg": "CentOS Linux release 7.4.1708 (Core) "
}
ok: [centos01] => {
"msg": "CentOS Linux release 7.4.1708 (Core) "
}
PLAY [Conectar a los servidores Debian] **
TASK [command] ******
changed: [debian02]
changed: [ansible01]
changed: [debian01]
TASK [debug] **********

300 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

ok: [debian02] => {


"msg": "9.3"
}
ok: [debian01] => {
"msg": "9.3"
}
ok: [ansible01] => {
"msg": "9.4"
}
PLAY RECAP **********
ansible01 : ok=4 changed=1 unreachable=0 failed=0
centos01 : ok=4 changed=1 unreachable=0 failed=0
centos02 : ok=4 changed=1 unreachable=0 failed=0
debian01 : ok=4 changed=1 unreachable=0 failed=0
debian02 : ok=4 changed=1 unreachable=0 failed=0

MÓDULOS MENSAJERÍA
Estos módulos sirven para gestionar RabbitMQ.
rabbitmq_binding Administra rabbitMQ bindings.
rabbitmq_exchange Administra rabbitMQ exchanges.
rabbitmq_parameter Añade o elimina parámetros de RabbitMQ.
rabbitmq_plugin Administra RabbitMQ plugins.
rabbitmq_policy Administra políticas en RabbitMQ.
rabbitmq_queue Administra rabbitMQ queues.
rabbitmq_user Añade o elimina usuarios de RabbitMQ.
rabbitmq_vhost Administra el estado de virtual hosts.

MÓDULOS CRIPTOGRAFÍA
Estos módulos sirven para hacer llamadas a OpenSSL.

openssl_certificate Genera o comprueba certificados OpenSSL.


openssl_csr Genera Certificate Signing Request(CSR).
openssl_privatekey Genera claves privadas OpenSSL.
openssl_publickey Genera una clave pública desde una clave
privada.

© Alfaomega-RC Libros 301


ANSIBLE

EJEMPLO

En el siguiente ejemplo se crea una clave privada, se generan una petición de


certificado (CSR) y un certificado para un servidor y se guarda la clave pública para
la clave privada.

Contenido del playbook.


- name: Crear certificados
hosts: servidor
gather_facts: False
tasks:
- name: Crear clave privada
openssl_privatekey:
path: /root/ssl/libroansible.oforte.net.key
state: present
- name: Crear petición de certificado firmado (CSR)
openssl_csr:
path: /root/ssl/ansible01.libroansible.oforte.net.csr
privatekey_path: /root/ssl/libroansible.oforte.net.key
country_name: ES
organization_name: Oforte
email_address: alberto@oforte.net
common_name: libroansible.oforte.net
- name: Generar certificado auto firmado
openssl_certificate:
path: /root/ssl/ansible01.libroansible.oforte.net.crt
privatekey_path: /root/ssl/libroansible.oforte.net.key
csr_path: /root/ssl/libroansible.oforte.net.csr
provider: selfsigned
- name: Generar clave pública desde la privada
openssl_publickey:
path: /root/ssl/libroansible.oforte.net.pem
privatekey_path: /root/ssl/libroansible.oforte.net.key

Ficheros generados y comprobación.


# ls -1tr /root/ssl/
libroansible.oforte.net.key
ansible01.libroansible.oforte.net.csr
ansible01.libroansible.oforte.net.crt
libroansible.oforte.net.pem
# openssl x509 -in ansible01.libroansible.oforte.net.crt -text -noout
Certificate:
Data:

302 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

Version: 3 (0x2)
Serial Number: 72527 (0x11b4f)
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=ES, ST=Pontevedra, L=Vigo, O=OforteNet,
CN=libroansible.oforte.net/emailAddress=alberto@oforte.net
Validity
Not Before: Apr 1 16:58:19 2018 GMT
Not After : Mar 29 16:58:19 2028 GMT
Subject: C=ES, ST=Pontevedra, L=Vigo, O=OforteNet,
CN=libroansible.oforte.net/emailAddress=alberto@oforte.net
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
[...]

MÓDULOS HERRAMIENTAS DE RED


Estos módulos sirven para hacer llamadas a diferentes acciones de red.

cloudflare_dns Gestiona registros DNS Cloudflare.


Interfaz con dnsimple.com (un servicio de
dnsimple alojamiento de DNS).
Interfaz con dnsmadeeasy.com (un servicio de
dnsmadeeasy alojamiento de DNS).
Administra registros de dominio en Exoscale
exo_dns_domain DNS API.
exo_dns_record Administra registros DNS en Exoscale DNS.
Descarga archivos de HTTP, HTTPS o FTP al
get_url nodo.
Habilita, deshabilita y establece los pesos
para los servidores back-end de HAProxy
haproxy usando comandos de socket.
infinity Administra Infinity IPAM usando Rest API.
Recupera la IP pública de su puerta de
ipify_facts enlace de Internet.
Recupera datos de geolocalización de IP de
ipinfoio_facts la dirección IP de un host.
ldap_attr Agrega o elimina valores de atributo LDAP.
ldap_entry Agrega o elimina entradas LDAP.

© Alfaomega-RC Libros 303


ANSIBLE

lldp Obtiene detalles reportados por lldp.


nmcli Administra redes.
nsupdate Administra registros DNS.
omapi_host Configura los hosts de OMAPI.
Recupera hechos para un dispositivo que usa
snmp_facts SNMP.
slurp Comprime un archivo de nodos remotos.
uri Interactúa con los servicios web.

MÓDULO GET_URL

En el siguiente ejemplo se descargan dos librerías jQuery dentro del directorio


web.
Contenido del playbook.
- name: Descargar ficheros jQuery
hosts: servidor
tasks:
- name: Crear directorio
file:
path: /var/www/html/js/
state: directory
owner: www-data
group: www-data
- name: Descargar librerias
get_url:
dest: /var/www/html/js/
url: "{{ item }}"
owner: www-data
group: www-data
mode: 0644
with_items:
- https://code.jquery.com/jquery-3.3.1.min.js
- http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js

Comprobación de la descarga.
# ls -l /var/www/html/js/
total 284
-rw-r--r-- 1 www-data www-data 86927 Apr 1 19:47 jquery-3.3.1.min.js
-rw-r--r-- 1 www-data www-data 200143 Apr 1 19:47 jquery.mobile-
1.4.5.min.js

304 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

MÓDULO HAPROXY

En el siguiente ejemplo se deshabilita un nodo del backend.

Estado actual.

Contenido del playbook.


- name: Deshabilitar nodo de HAproxy.
hosts: servidor
gather_facts: False
tasks:
- haproxy:
state: disabled
host: 'debian02'
backend: web-debian
socket: /var/run/haproxy/admin.sock
Estado después de ejecutar el playbook.

MÓDULO LDAP_ENTRY

En el siguiente ejemplo se añade un usuario al directorio LDAP.

Contenido del playbook.


- name: Make sure we have an admin user
hosts: servidorldap
gather_facts: False
tasks:
- name: Instalar librería requerida
pip:
name: python-ldap
state: latest
- name: Añadir usuario

© Alfaomega-RC Libros 305


ANSIBLE

ldap_entry:
server_uri: ldap://ldap.oforte.net/
bind_dn: cn=admin,dc=oforte,dc=net
bind_pw: 1yGCd11tAwnh
dn: cn=Ansible,ou=People,dc=oforte,dc=net
objectClass:
- inetOrgPerson
- top
- posixAccount
attributes:
description: Usuario creado por Ansible
givenName: Ansible
sn: Creado
uid: ansible
uidNumber: 1005
gidNumber: 1005
homeDirectory: /home/ansible
mail: ansible@oforte.net
userPassword: "{SSHA}4Iz+b/kLfe9OZ2/MEAi+d13hem"

Comprobación de la creación del usuario.

306 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

MÓDULO NSUPDATE

En el siguiente ejemplo se utiliza nsupdate para añadir un registro dentro de


un servidor DNS (bind9).

Contenido del playbook.


- name: Crear registro
hosts: servidordns
gather_facts: False
tasks:
- name: Añadir ansible.oforte.net
nsupdate:
key_name: "keyoforte"
key_secret: "n4jFPx2K50HbuPchG/pvLA=="
server: "10.10.10.6"
zone: "oforte.net"
record: "ansible"
Comprobación de creación del registro.
# dig @10.10.10.6 +short ansible.oforte.net
10.10.10.222

MÓDULO SLURP

Este módulo es similar a fetch pero no copia el fichero al nodo Ansible sino que
devuelve el valor en una variable con formato base64. En el siguiente ejemplo
leemos el contenido de un fichero del nodo administrado.

Contenido del playbook.


- name: Leer fichero del servidor
hosts: servidor
gather_facts: False
tasks:
- slurp:
src: /etc/hostname
register: nombre
- debug: msg="Nombre {{ nombre["content"] | b64decode }}"
Salida del playbook.
PLAY [Leer fichero del servidor] *************
TASK [slurp] ***********
ok: [ipaserver]

© Alfaomega-RC Libros 307


ANSIBLE

TASK [debug] **********


ok: [ipaserver] => {
"msg": "Nombre libroansible.oforte.net\n"
}

PLAY RECAP **********


ipaserver : ok=2 changed=0 unreachable=0 failed=0

MÓDULO URI

En el siguiente ejemplo se configura el index.html de un servidor web y se


consulta desde el servidor Ansible.

Contenido del playbook.


- name: Configurar index.html
hosts: debian01
remote_user: alberto
become: True
tasks:
- name: Crear index.html
copy:
dest: /var/www/html/index.html
content: "Hola desde {{ ansible_fqdn }}"
owner: www-data
group: www-data

- set_fact:
ip_servidor: "{{ ansible_host }}"
- name: Comprobar conexión a la web
uri:
url: "http://{{ ip_servidor }}"
return_content: yes
register: respuesta
delegate_to: localhost
- debug: msg="Respuesta {{ respuesta.content }}"
Mensaje mostrado por debug.
TASK [debug] **********
ok: [debian01] => {
"msg": "Respuesta Hola desde debian01.c.oforte-196215.internal"
}

308 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

MÓDULOS ALMACENAMIENTO
Estos módulos sirven para gestionar distintas plataformas de almacenamiento.

Infinidat
Crea, elimina o modifica NFS Exports
infini_export en Infinibox.
Crea, elimina o modifica NFS
Client(s) para existentes exports en
infini_export_client Infinibox.
Crea, elimina o modifica sistemas de
infini_fs ficheros en Infinibox.
Crea, elimina o modifica Hosts en
infini_host Infinibox.
Crea, elimina o modifica Pools en
infini_pool Infinibox.
Crea, elimina o modifica volúmenes
en Infinibox.
infini_vol
Netapp
Administra los agregados de cDOT
na_cdot_aggregate de NetApp.
Administra el protocolo cDOT de
NetApp y las licencias de
na_cdot_license funciones.
na_cdot_lun Administra NetApp cDOT luns.
na_cdot_qtree Administra qtrees.
na_cdot_svm Administra NetApp cDOT svm.
Configuración y administración de
na_cdot_user useradmin.
Configuración y administración de
na_cdot_user_role useradmin.
Administra los volúmenes cDOT de
na_cdot_volume NetApp.
Crea, elimina y actualiza grupos
netapp_e_amg espejo asíncronos.

© Alfaomega-RC Libros 309


ANSIBLE

Actualiza el rol de una matriz de


almacenamiento dentro de un
netapp_e_amg_role Asynchronous Mirror Group (AMG).
Lleva a cabo acciones de
sincronización en grupos espejo
netapp_e_amg_sync asíncronos.
Establece o actualiza la
contraseña para una matriz de
netapp_e_auth almacenamiento.
Obtiene información sobre NetApp
netapp_e_facts E.
Administra cachés de SSD de
netapp_e_flashcache NetApp.
netapp_e_host Administra hosts eseries.
Administra grupos de hosts de la
matriz de almacenamiento de
netapp_e_hostgroup NetApp.
Crea o elimina asignaciones de
LUN.
netapp_e_lun_mapping
Administra grupos de instantáneas.
netapp_e_snapshot_group
Crea y elimina imágenes de
netapp_e_snapshot_images instantáneas.
netapp_e_snapshot_volume Administra E / EF.
Agrega / elimina matrices del
netapp_e_storage_system proxy de servicios web.
Administra grupos de discos y pool
netapp_e_storagepool de discos.
Administra volúmenes de
almacenamiento (estándar y
netapp_e_volume delgado).
netapp_e_volume_copy Crea pares de copia de volumen.
sf_account_manager Administra cuentas de SolidFire.
Verifica la conectividad a MVIP y
sf_check_connections SVIP.
sf_snapshot_schedule_man Administra programas de
ager instantáneas de SolidFire.

310 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

sf_volume_access_group_m Administra grupos de acceso por


anager volumen de SolidFire.
Administra volúmenes de SolidFire.
sf_volume_manager
Purestorage
Administra grupos de hosts en Pure Storage
purefa_hg FlashArrays.
Administra hosts en Pure Storage
purefa_host FlashArrays.
Administra grupos de protección en Pure
purefa_pg Storage FlashArrays.
Administra instantáneas de volumen en Pure
purefa_snap Storage FlashArrays.
Administra volúmenes en Pure Storage
purefa_volume FlashArrays.
Zfs
zfs Gestiona zfs.
zfs_facts Obtiene facts sobre ZFS datasets.
zpool_facts Obtiene facts sobre ZFS pools.

MÓDULOS ADMINISTRACIÓN REMOTA

Estos módulos sirven para distintas utilidades de administración remota.

wakeonlan Envía un paquete de broadcast Wake on LAN (WoL).


Foreman
foreman Gestiona Foreman Resources.
katello Gestiona Katello Resources.
Hpilo
hpilo_boot Sistema de arranque utilizando medios
específicos a través de la interfaz HP iLO.
hpilo_facts Reúne datos a través de una interfaz HP iLO.
Configura la interfaz HP iLO utilizando
hponcfg hponcfg.

© Alfaomega-RC Libros 311


ANSIBLE

Imc
imc_rest Gestiona hardware Cisco IMC usando su REST API.
Ipmi
ipmi_boot Gestiona el orden de los dispositivos de inicio.
ipmi_power Administrador de energía para el servidor.
Manageiq
manageiq_provider Gestiona un proveedor en ManageIQ.
manageiq_user Gestiona usuarios en ManageIQ.
Oneview
oneview_ethernet Administra los recursos de la red Ethernet
_network de OneView.
oneview_ethernet Recupera los datos sobre una o más de las
_network_facts redes Ethernet OneView.
oneview_fc_netwo Administra los recursos de red de canal de
rk fibra de OneView.
oneview_fc_netwo Recupera los hechos sobre una o más de las
rk_facts redes de canal de fibra OneView.
oneview_fcoe_net Administra los recursos de la red OneView
work FCoE.
oneview_fcoe_net Recupera los hechos sobre una o más de las
work_facts redes OneView FCoE.
oneview_network_ Administra los recursos del conjunto de
set redes HPE OneView.
oneview_network_ Recupera datos sobre los conjuntos de red
set_facts OneView.
oneview_san_mana Administra recursos de OneView SAN
ger Manager.
Stacki
stacki_host Agrega o elimina el host al front-end stacki.

MÓDULOS REDES
Ansible tiene módulos soportados para administrar la mayoría de dispositivos
de red de las empresas más reconocidas, entre ellas:

312 © Alfaomega-RC Libros


CAPÍTULO 5: MÓDULOS

Los módulos Arista EOS incluyen: eAPI,


comando, configuración y plantilla.

Construido sobre 100% API REST, Avi


Networks amplía los objetivos de
automatización que los clientes derivan de
una implementación de Ansible.

Módulos para:
Cisco IOS
Cisco IOS XR
Cisco NX-OS

Utiliza las API REST basadas en estándares


(NITRO) para administrar de forma
programática los dispositivos del
controlador de entrega de aplicaciones
(ADC) de NetScaler en todos los factores
de forma y las implementaciones híbridas /
multi-nube.
Cumulus Networks Linux NOS se puede
configurar completamente con los mismos
libros de jugadas de Ansible que las
organizaciones están usando en otros
sistemas.
El uso de Ansible para aprovisionar y
administrar sus conmutadores Dell EMC le
permitirá implementar rápidamente nuevos
dispositivos, cambiar las configuraciones
de red.
Los usuarios de F5 pueden automatizar y
organizar utilizando Ansible a través de
una serie de integraciones con los módulos
llamados F5 BIG-IP API. Estos módulos
aprovechan el soporte API completo
implementado en hardware F5 BIG-IP y
plataformas virtuales.

© Alfaomega-RC Libros 313


ANSIBLE

Cuando el módulo de red se aplica en la


plataforma Ansible, NETCONF o CLI se
pueden usar para desplegar y configurar
automáticamente los conmutadores de la
serie CloudEngine, lo que permite que el
equipo de administración de red realice O
& M de manera más fácil y eficiente.
La combinación de las herramientas de
automatización y orquestación de Ansible y
Juniper reúne el conocimiento y la
experiencia de desarrolladores, operadores
y administradores de soluciones de TI con
experiencia en todas las organizaciones.

La solución conjunta incluye módulos


Ansible desarrollados específicamente para
Nokia SR OS.

La integración de Mellanox ONYXTM con


Ansible y Red Hat® Ansible® Tower junto
con el soporte de Zero Touch Provisioning,
le permite automatizar el
aprovisionamiento, la configuración y el
mantenimiento de los switches de manera
confiable.

Lenovo CNOS (sistema operativo de red en


la nube).

La integración de Ansible con los switches


CNOS brinda automatización de flujo de
trabajo de alta velocidad en la nube al
centro de datos.

Los módulos Ansible para Palo Alto


Networks se pueden usar para configurar
toda la familia de firewalls de la próxima
generación, tanto factores de forma
virtualizados físicos como Panorama.

314 © Alfaomega-RC Libros


CARACTERÍSTICAS
AVANZADAS

En este capítulo detallaremos características avanzadas al escribir Playbooks.

ETIQUETAS (TAGS)
Las etiquetas permiten especificar selectivamente qué tareas se ejecutarán o
se omitirán. Se pueden utilizar a nivel de Play, Role o Task (tarea), aunque se
aplican a nivel de tarea: si se especifican las etiquetas a un rol, se asignará esa
etiqueta a todas las tareas dentro del rol. La sintaxis es la siguiente:

- name: Play para instalar apache


hosts: all
tags: apache
pre_tasks:
- name: Instalar apache
apt:
name: apache2
state: present
tags: ["instalar", "reinstalar"]
roles:
- name: agonzalezrh.ejemplorol
tags: configurar
ANSIBLE

Para nuestros ejemplos se utilizará el siguiente playbook con diferentes


etiquetas para mostrar el funcionamiento.

- name: Ejemplo de etiquetas


hosts: localhost
gather_facts: False
tasks:
- debug: msg="Tarea con etiqueta DEV"
tags: dev
- debug: msg="Tarea con etiqueta TEST"
tags: test
- debug: msg="Tarea con etiqueta PROD"
tags: prod
- debug: msg="Tarea con etiqueta DEV y TEST"
tags: ["dev", "test"]

En la línea de comandos usando el comando ansible-playbook podemos


utilizar las opciones:

--list-tags Lista las etiquetas en cada Play del


Playbook.
--tags etiqueta(s) Ejecuta las tareas con alguna de las
tareas especificadas.
--tags etiqueta(s) No ejecuta las tareas que contenga
alguna de las tareas especificadas.

En los siguientes ejemplos vemos el resultado utilizando dichas opciones.

Listar las etiquetas del playbook.


# ansible-playbook --list-tags tags2.yml
playbook: tags2.yml

play #1 (localhost): Ejemplo de etiquetas TAGS: []


TASK TAGS: [always, dev, prod, test]
Ejecutar las tareas con la etiqueta "dev".
# ansible-playbook --tags dev tags2.yml
PLAY [Ejemplo de etiquetas] ****************
TASK [debug] **********
ok: [localhost] => {
"msg": "Tarea con etiqueta DEV"
}

316 © Alfaomega-RC Libros


CAPÍTULO 6: CARACTERÍSTICAS AVANZADAS

TASK [debug] **********


ok: [localhost] => {
"msg": "Tarea con etiqueta DEV y TEST"
}
PLAY RECAP **********
localhost : ok=2 changed=0 unreachable=0 failed=0
No ejecutar las tareas que tengan la etiqueta dev o test.
# ansible-playbook --skip-tags dev,test tags2.yml
PLAY [Ejemplo de etiquetas] **
TASK [debug] **********
ok: [localhost] => {
"msg": "Tarea con etiqueta PROD"
}
PLAY RECAP **********
localhost : ok=1 changed=0 unreachable=0 failed=0

Existen dos etiquetas especiales predefinidas:

● always: esta tarea se ejecutará siempre independientemente de que se


especifica en la opción --tags. (Excepto si se utiliza --skip-tags always).
● tagged: solo se ejecutarán las tareas etiquetadas.
● untagged: solo se ejecutarán las tareas no etiquetadas.

Es posible utilizar --list-tasks para listar las tareas que se aplican a las etiquetas
seleccionadas. En el anterior ejemplo se incluyen estas tareas:

- debug: msg="Tarea con etiqueta always"


tags: always
- debug: msg="Tarea sin etiqueta"
Ejemplos
# ansible-playbook --list-tasks tags2.yml --tags prod
playbook: tags2.yml
play #1 (localhost): Ejemplo de etiquetas TAGS: []
tasks:
debug TAGS: [prod]
# ansible-playbook --tags untagged tags2.yml
PLAY [Ejemplo de etiquetas] **
TASK [debug] **********
ok: [localhost] => {
"msg": "Tarea con etiqueta always"
}
TASK [debug] **********

© Alfaomega-RC Libros 317


ANSIBLE

ok: [localhost] => {


"msg": "Tarea sin etiqueta"
}
PLAY RECAP **********
localhost : ok=2 changed=0 unreachable=0 failed=0

LOOKUPS
La directiva lookup nos permite obtener datos desde el servidor que está
ejecutando el Playbook. Por ejemplo si queremos leer el fichero /etc/motd desde
donde ejecutamos ansible-playbook podemos utilizar la siguiente sintaxis para
obtener el contenido del fichero.
debug: msg="{{ lookup('file', '/etc/motd') }}"

Es importante recordar que la tarea se ejecutará en el nodo especificado, pero


la información será obtenida del nodo que ejecuta ansible-playbook. La lista
completa de plugins que se pueden utilizar se muestra en la siguiente tabla (en
negrita los que se detallarán).

cartesian Devuelve el producto cartesiano de las


listas.
chef_databag Obtiene datos de un Databag Chef.
consul_kv Capta metadatos de un almacén de valores
clave de cónsul.
credstash Recupera secretos de Credstash en AWS.
csvfile Lee datos de un archivo TSV o CSV.
cyberarkpassword Obtiene secretos de CyberArk AIM.
dict Devuelve elementos de par clave / valor
de un diccionario.
dig Consulta DNS utilizando la biblioteca
dnspython.
dnstxt Consulta los campos txt DNS de un
dominio.
env Lee el valor de las variables de
entorno.
etcd Obtiene información del servidor de etc.

318 © Alfaomega-RC Libros


CAPÍTULO 6: CARACTERÍSTICAS AVANZADAS

file Lee los contenidos del archivo.


fileglob Lista archivos que coincidan con un
patrón.
filetree Recursivamente une todos los archivos en
un árbol de directorios.
first_found Devuelve el primer archivo encontrado de
la lista.
flattened Lista única de regreso totalmente
aplanada.
hashi_vault Recupera secretos de la bóveda de
HasihCorp.
hiera Obtiene información de los datos de
hiera.
indexed_items Reescribe listas para devolver
'elementos indexados'.
ini Lee datos de un archivo ini.
inventory_hostnames Lista de hosts de inventario que
coinciden con un patrón de host.
items Lista de artículos.
keyring Agarra secretos del llavero OS.
lastpass Obtiene datos del último paso.
lines Lee líneas desde el comando.
list Simplemente devuelve lo que se le da.
mongodb Información de búsqueda de MongoDB.
nested Compone una lista con elementos anidados
de otras listas.
password Recupera o genera una contraseña
aleatoria, almacenada en un archivo.
passwordstore Administra contraseñas con la utilidad
de pase de passwordstore.org.
pipe Lee salida de un comando.
random_choice Devuelve elemento aleatorio de la lista.
redis_kv Obtiene datos de Redis.
sequence Genera una lista basada en una secuencia
numérica.

© Alfaomega-RC Libros 319


ANSIBLE

shelvefile Lee las claves de un fichero shelve de


Python.
subelements Atraviesa la clave anidada de una lista
de diccionarios.
template Recupera el contenido del archivo
después de plantillas con Jinja2.
together Fusiona listas en listas sincronizadas.
url Devuelve contenidos desde URL.

CSVFILE

Este plugin nos permite leer datos de un fichero CSV. Los parámetros son:

col=1 Columna para regresar (0 índice).


default Qué devolver si el valor no se encuentra en
el archivo.
delimiter=tab Separador de campo en el archivo, para una
pestaña puede especificar "TAB" o "t".
encoding=utf-8 Codificación (conjunto de caracteres) del
archivo CSV utilizado.
file=ansible.csv Nombre del archivo CSV / TSV para abrir.

Ejemplo se lee el fichero datos.csv del servidor donde se ejecuta ansible-


playbook:

# cat datos.csv
agonzalez,Alberto,Gonzalez,alberto@oforte.net
jveipen,Jonathan,Veites,jveipen@oforte.net
- name: Plugin csvfile
hosts: ansible01
gather_facts: False
tasks:
- debug:
msg: "Correo {{ lookup('csvfile','agonzalez
file=datos.csv delimiter=, col=3') }}"
PLAY [Plugin csvfile] ****
TASK [debug] **********
ok: [ansible01] => {
"msg": "Correo alberto@oforte.net"

320 © Alfaomega-RC Libros


CAPÍTULO 6: CARACTERÍSTICAS AVANZADAS

}
PLAY RECAP **********
ansible01 : ok=1 changed=0 unreachable=0 failed=0

DIG

Este plugin nos permite hacer una consola DNS. Los parámetros son los
siguientes:

termino Dominio (s) para consultar


flat=yes Si 0 cada registro se devuelve como un
diccionario, de lo contrario, una cadena
qtype=A Tipo de registro para consulta

En el siguiente ejemplo mostramos la IP de un dominio especificado.

- name: Plugin dig


hosts: ansible01
gather_facts: False
tasks:
- debug:
msg: "IP {{ lookup('dig','oforte.net') }}"
TASK [debug] **********
ok: [ansible01] => {
"msg": "IP 37.139.7.43"
}

ENV

Este plugin nos permite obtener el valor de una variable de entorno. En el


siguiente ejemplo mostramos el valor de la variable de entorno LANG.

- name: Plugin env


hosts: ansible01
gather_facts: False
tasks:
- debug:
msg: "Idioma es{{ lookup('env','LANG') }}"
TASK [debug] **********
ok: [ansible01] => {

© Alfaomega-RC Libros 321


ANSIBLE

"msg": "Idioma esen_GB.UTF-8"


}

FILE

Este plugin nos permite obtener el contenido de un fichero. En el siguiente


ejemplo mostramos el contenido del fichero /etc/hostname.

- name: Plugin file


hosts: ansible01
gather_facts: False
tasks:
- debug:
msg: "Contenido {{ lookup('file','/etc/hostname') }}"

TASK [debug] **********


ok: [ansible01] => {
"msg": "Contenido cloud.oforte.net"
}

INI

Este plugin nos permite leer datos de un fichero de configuración INI. Como
ejemplo se lee el fichero ansible.cfg del servidor donde se ejecuta ansible-
playbook, para mostrar la ruta del directorio de los roles.

- name: Plugin ini


hosts: ansible01
gather_facts: False
tasks:
- name: Mostrar ruta de los roles
debug:
msg: "{{ lookup('ini','roles_path section=defaults
file=/etc/ansible/ansible.cfg') }}"

TASK [Mostrar ruta de los roles] ************


ok: [ansible01] => {
"msg": "/etc/ansible/roles"
}

322 © Alfaomega-RC Libros


CAPÍTULO 6: CARACTERÍSTICAS AVANZADAS

PASSWORD

Este plugin nos permite generar una contraseña y guardarla en un fichero. En


el siguiente ejemplo el playbook se ejecuta en el nodo llamado cloud y se conecta
al nodo ansible01.

Contenido del playbook.


- name: Plugin password
hosts: ansible01
gather_facts: False
tasks:
- name: Generar una contraseña y guardarla localmente
set_fact:
clave: "{{ lookup('password','/tmp/clave_ansible01') }}"
- name: Copiar clave a un fichero remoto
copy:
dest: /tmp/clave_generada_en_cloud
content: "{{ clave }}"
Fichero generado donde se ha ejecutado ansible-playbook.
cloud# cat /tmp/clave_ansible01
WPdfG3hl3zK:chtnvtse
Fichero generado con el módulo copy en el nodo remoto.
alberto@ansible01:~$ cat /tmp/clave_generada_en_cloud
WPdfG3hl3zK:chtnvtse

PIPE

Este plugin nos permite ejecutar comandos en el nodo local.

- name: Plugin pipe


hosts: ansible01
gather_facts: False
tasks:
- debug:
msg: "Nodo donde se ejecuta ansible {{ lookup('pipe',
'uname -n') }}"
ok: [ansible01] => {
"msg": "Nodo donde se ejecuta ansible cloud.oforte.net"
}

© Alfaomega-RC Libros 323


ANSIBLE

URL

Este plugin nos permite leer el contenido de una página web. Los parámetros
son:

split_lines=yes Marca para controlar si el contenido se


devuelve como una lista de líneas o como
un solo blob de texto.
use_proxy=yes Marca para controlar si la búsqueda
observará variables de entorno de proxy
HTTP cuando estén presentes.
validate_certs=yes Marca para controlar la validación del
certificado SSL.

En el siguiente ejemplo, se obtiene el contenido de la clave GPG del repositorio


EPEL. Esto es muy útil si los nodos administrados no tienen acceso a internet.

Contenido del playbook.


- name: Plugin url
hosts: centos01
become: True
gather_facts: False
tasks:
- name: Obtener clave GPG
set_fact:
epel_gpg: "{{
lookup('url','https://archive.fedoraproject.org/pub/epel/RPM-GPG-
KEY-EPEL-7', split_lines=false) }}"
- name: Almacenar clave GPG
copy:
dest: /root/epel.key
content: "{{ epel_gpg }}"
Comprobación.
# cat epel.key
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.4.11 (GNU/Linux)
mQINBFKuaIQBEAC1UphXwMqCAarPUH/ZsOFslabeTVO2pDk5YnO96f+rgZB7xArB
OSeQk7B90iqSJ85/c72OAn4OXYvT63gfCeXpJs5M7emXkPsNQWWSju99lW+AqSNm
jYWhmRlLRGl0OO7gIwj776dIXvcMNFlzSPj00N2xAqjMbjlnV2n2abAE5gq6VpqP
vFXVyfrVa/ualogDVmf6h2t4Rdpifq8qTHsHFU3xpCz+T6/dGWKGQ42ZQfTaLnDM
jToAsmY0AyevkIbX6iZVtzGvanYpPcWW4X0RDPcpqfFNZk643xI4lsZ+Y2Er9Yu5

324 © Alfaomega-RC Libros


CAPÍTULO 6: CARACTERÍSTICAS AVANZADAS

S/8x0ly+tmmIokaE0wwbdUu740YTZjCesroYWiRg5zuQ2xfKxJoV5E+Eh+tYwGDJ
n6HfWhRgnudRRwvuJ45ztYVtKulKw8QQpd2STWrcQQDJaRWmnMooX/PATTjCBExB
9dkz38Druvk7IkHMtsIqlkAOQMdsX1d3Tov6BE2XDjIG0zFxLduJGbVwc/6rIc95
T055j36Ez0HrjxdpTGOOHxRqMK5m9flFbaxxtDnS7w77WqzW7HjFrD0VeTx2vnjj
GqchHEQpfDpFOzb8LTFhgYidyRNUflQY35WLOzLNV+pV3eQ3Jg11UFwelSNLqfQf
uFRGc+zcwkNjHh5yPvm9odR1BIfqJ6sKGPGbtPNXo7ERMRypWyRz0zi0twARAQAB
tChGZWRvcmEgRVBFTCAoNykgPGVwZWxAZmVkb3JhcHJvamVjdC5vcmc+iQI4BBMB
AgAiBQJSrmiEAhsPBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRBqL66iNSxk
5cfGD/4spqpsTjtDM7qpytKLHKruZtvuWiqt5RfvT9ww9GUUFMZ4ZZGX4nUXg49q
ixDLayWR8ddG/s5kyOi3C0uX/6inzaYyRg+Bh70brqKUK14F1BrrPi29eaKfG+Gu
MFtXdBG2a7OtPmw3yuKmq9Epv6B0mP6E5KSdvSRSqJWtGcA6wRS/wDzXJENHp5re
9Ism3CYydpy0GLRA5wo4fPB5uLdUhLEUDvh2KK//fMjja3o0L+SNz8N0aDZyn5Ax
CU9RB3EHcTecFgoy5umRj99BZrebR1NO+4gBrivIfdvD4fJNfNBHXwhSH9ACGCNv
HnXVjHQF9iHWApKkRIeh8Fr2n5dtfJEF7SEX8GbX7FbsWo29kXMrVgNqHNyDnfAB
VoPubgQdtJZJkVZAkaHrMu8AytwT62Q4eNqmJI1aWbZQNI5jWYqc6RKuCK6/F99q
thFT9gJO17+yRuL6Uv2/vgzVR1RGdwVLKwlUjGPAjYflpCQwWMAASxiv9uPyYPHc
ErSrbRG0wjIfAR3vus1OSOx3xZHZpXFfmQTsDP7zVROLzV98R3JwFAxJ4/xqeON4
vCPFU6OsT3lWQ8w7il5ohY95wmujfr6lk89kEzJdOTzcn7DBbUru33CQMGKZ3Evt
RjsC7FDbL017qxS+ZVA/HGkyfiu4cpgV8VUnbql5eAZ+1Ll6Dw==
=hdPa
-----END PGP PUBLIC KEY BLOCK-----

FILTROS
Cuando se utilizan plantillas (que usan el formato Jinja2) es posible utilizar
filtros para realizar distintas tareas sobre el contenido. Un ejemplo es transformar
un diccionario a formato JSON. La sintaxis de los filtros es la siguiente:

{{ mi_variable | filtro_a_aplicar }}

Las funciones internas de Ansible para las plantillas son las siguientes:

Filtros formato base64 y uuid.


b64encode Codificar cadenas con Base64
b64decode Descodificar cadenas codificadas en Base64
to_uuid Crear un UUID a partir de una cadena
Contenido ejemplo del playbook.
- name: Ejemplos filtros base64 y uuid
hosts: localhost
gather_facts: False

© Alfaomega-RC Libros 325


ANSIBLE

tasks:
- name: Cifrar texto en base64
set_fact: cifrado="{{ 'libro ansible' | b64encode }}"
- debug: var=cifrado
- name: Descifrar texto
debug:
msg: "Texto descifrado: {{ cifrado | b64decode }} "
- name: Mostrar UUID del hostname
debug: msg="UUUID {{ 'libro.oforte.net' | to_uuid }}"
Resultado de la ejecución.
PLAY [Ejemplos filtros base64 y uuid] ******
TASK [Cifrar texto en base64] **************
ok: [localhost]TASK [debug] **********
ok: [localhost] => {
"cifrado": "bGlicm8gYW5zaWJsZQ=="
}
TASK [Descifrar texto] ***
ok: [localhost] => {
"msg": "Texto descifrado: libro ansible "
}
TASK [Mostrar UUID del hostname] ********
ok: [localhost] => {
"msg": "UUUID 6b058c2e-e43c-51d9-9092-4050d98d0105"
}
PLAY RECAP **********
localhost : ok=4 changed=0 unreachable=0 failed=0

Filtros formato JSON y YAML.


to_json Convierte valor en JSON.
to_nice_json Convierte cadena en JSON bonito.
from_json Lectura en algunos datos formateados JSON.
to_yaml Convierte el valor en YAML.
to_nice_yaml Convierte el valor en YAML bonito.
from_yaml Lectura en datos formateados YAML.
Contenido ejemplo del playbook.
- name: Ejemplos filtros json/yaml
hosts: localhost
gather_facts: False
vars:
datos_json: '{"alberto":{"correo":"alberto@oforte.net"}}'

326 © Alfaomega-RC Libros


CAPÍTULO 6: CARACTERÍSTICAS AVANZADAS

datos_yaml: "alberto:\n correo: alberto@oforte.net"


usuarios:
agonzalez:
nombre: Alberto
apellido: Gonzalez
email: alberto@oforte.net
jveipen:
nombre: Jonathan
apellido: Veites
email: jveipen@oforte.net
tasks:
- name: Mostrar usuarios en formato JSON
debug: msg="{{ usuarios | to_json }}"
- name: Mostrar usuarios en formato JSON (multiple líneas)
debug: msg="{{ (usuarios | to_nice_json).split('\n') }}"
- name: Leer una variable en formato JSON
set_fact: datos="{{ datos_json | from_json }}"
- debug: msg="Correo {{ datos.alberto.correo }}"
- name: Mostrar usuarios en formato YAML
debug: msg="{{ usuarios | to_yaml }}"
- name: Mostrar usuarios en formato YAML (multiple líneas)
debug: msg="{{ (usuarios | to_nice_yaml).split('\n') }}"
- name: Leer una variable en formato YAML
set_fact: datos2="{{ datos_yaml | from_yaml }}"
- debug: msg="Correo {{ datos2.alberto.correo}}"
Resultado de la ejecución.
PLAY [Ejemplos filtros json/yaml] ***********
TASK [Mostrar usuarios en formato JSON] ***
ok: [localhost] => {
"msg": "{\"jveipen\": {\"nombre\": \"Jonathan\",
\"email\": \"jveipen@oforte.net\", \"apellido\":
\"Veites\"}, \"agonzalez\": {\"nombre\": \"Alberto\",
\"email\": \"alberto@oforte.net\", \"apellido\":
\"Gonzalez\"}}"
}
TASK [Mostrar usuarios en formato JSON (multiple líneas)]
***********
ok: [localhost] => {
"msg": [
"{",
" \"agonzalez\": {",
" \"apellido\": \"Gonzalez\", ",
" \"email\": \"alberto@oforte.net\", ",
" \"nombre\": \"Alberto\"",

© Alfaomega-RC Libros 327


ANSIBLE

" }, ",
" \"jveipen\": {",
" \"apellido\": \"Veites\", ",
" \"email\": \"jveipen@oforte.net\", ",
" \"nombre\": \"Jonathan\"",
" }",
"}"
]
}
TASK [Leer una variable en formato JSON] **
ok: [localhost]
TASK [debug] **********
ok: [localhost] => {
"msg": "Correo alberto@oforte.net"
}
TASK [Mostrar usuarios en formato YAML] ***
ok: [localhost] => {
"msg": "agonzalez: {apellido: Gonzalez, email:
alberto@oforte.net, nombre: Alberto}\njveipen: {apellido:
Veites, email: jveipen@oforte.net, nombre: Jonathan}\n"
}
TASK [Mostrar usuarios en formato YAML (multiple líneas)]
*****
ok: [localhost] => {
"msg": [
"agonzalez:",
" apellido: Gonzalez",
" email: alberto@oforte.net",
" nombre: Alberto",
"jveipen:",
" apellido: Veites",
" email: jveipen@oforte.net",
" nombre: Jonathan",
""
]
}
TASK [Leer una variable en formato YAML] ***
ok: [localhost]
TASK [debug] **********
ok: [localhost] => {
"msg": "Correo alberto@oforte.net"
}
PLAY RECAP **********
localhost : ok=8 changed=0 unreachable=0 failed=0

328 © Alfaomega-RC Libros


CAPÍTULO 6: CARACTERÍSTICAS AVANZADAS

Filtros para rutas de fichero.


basename Devuelve el nombre base de la ruta del nombre
de ruta.
dirname Devuelve el nombre del directorio de la ruta
del nombre de ruta.
expanduser Expande una ruta que contiene un carácter de
virgulilla (~)
realpath Obtiene la ruta real de un enlace.
splitext Para obtener la raíz y la extensión de una
ruta o nombre de archivo.
Contenido ejemplo del playbook.
- name: Ejemplos filtros rutas
hosts: localhost
gather_facts: False
vars:
ruta1: /etc/alternatives/java
ruta2: ~/.ssh/id_rsa.pub
tasks:
- name: Obtener el fichero de una ruta
debug: msg="{{ ruta1 | basename }}"
- name: Obtener el directorio de una ruta
debug: msg="{{ ruta1 | dirname }}"
- name: Convertir ~ a la ruta del usuario
debug: msg="{{ ruta2 | expanduser }}"
- name: Mostrar la ruta a donde apunta un enlace
debug: msg="{{ ruta1 | realpath }}"
- name: Separar el nombre y extensión
debug: msg="{{ 'apache2.conf' | splitext }}"

Resultado de la ejecución.
PLAY [Ejemplos filtros rutas] ****************
TASK [Obtener el fichero de una ruta] *******
ok: [localhost] => {
"msg": "java"
}
TASK [Obtener el directorio de una ruta] ***
ok: [localhost] => {
"msg": "/etc/alternatives"
}
TASK [Convertir ~ a la ruta del usuario] ****
ok: [localhost] => {

© Alfaomega-RC Libros 329


ANSIBLE

"msg": "/root/.ssh/id_rsa.pub"
}
TASK [Mostrar la ruta a donde apunta un enlace] ********
ok: [localhost] => {
"msg": "/usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java"
}
TASK [Separar el nombre y extensión] *****
ok: [localhost] => {
"msg": "('apache2', '.conf')"
}
PLAY RECAP **********
localhost : ok=4 changed=0 unreachable=0 failed=0

Filtros para hashing.


hash Obtener el hash de una cadena, opciones: md5,
sha1, sha224, sha256, sha384, sha512.
checksum Obtener un checksum de una cadena.
password_hash Obtener clave hash de una, opciones: md5,
sha256, sha512.
Contenido ejemplo del playbook.
- name: Ejemplo filtros hashing
hosts: localhost
gather_facts: False
tasks:
- name: Filtro hash
debug: msg="{{ 'libro ansible'|hash(item) }}"
with_items:
- md5
- sha1
- sha224
- sha256
- sha384
- sha512
- name: Filtro checksum
debug: msg="{{ 'libro ansible'|checksum }}"
- name: Filtro password_hash
debug: msg="{{ 'libro ansible'|password_hash(item) }}"
with_items:
- md5
- sha256
- sha512

330 © Alfaomega-RC Libros


CAPÍTULO 6: CARACTERÍSTICAS AVANZADAS

Resultado de la ejecución.
PLAY [Ejemplo filtros hashing] **************
TASK [Filtro hash] *****
ok: [localhost] => (item=md5) => {
"changed": false,
"item": "md5",
"msg": "c57f3f9c93c9d62baeec82bd2376e3a2"
}
ok: [localhost] => (item=sha1) => {
"changed": false,
"item": "sha1",
"msg": "8fdae2a189f730f7b25e34adc89423e730c1b75b"
}
ok: [localhost] => (item=sha224) => {
"changed": false,
"item": "sha224",
"msg": "7186a5d40164ea5b8414b00f7beed86f7b6c33c589beb13a7168c10e"
}
ok: [localhost] => (item=sha256) => {
"changed": false,
"item": "sha256",
"msg": "1e027b4cf0df2e7efe98a090c812180b315312728fbe80301ca02678659cda8a"
}
ok: [localhost] => (item=sha384) => {
"changed": false,
"item": "sha384",
"msg":
"7ddd65f5abee22d6662919bd83d20cd57c3eba74acb3861cb40e8357d2e2cdc7bb9aa78efa
87e65f79b9c6a0f2857d49"
}
ok: [localhost] => (item=sha512) => {
"changed": false,
"item": "sha512",
"msg":
"acc201b41e895774b870569ede9dd89c68af4e60b5ab558f5feb68f5ccabe16e368bf9137e
17796759f1a9296203ba61dccf54a4a27031c515082deeaf51e0ec"
}
TASK [Filtro checksum] ***
ok: [localhost] => {
"msg": "8fdae2a189f730f7b25e34adc89423e730c1b75b"
}
TASK [Filtro password_hash] **
ok: [localhost] => (item=md5) => {
"changed": false,

© Alfaomega-RC Libros 331


ANSIBLE

"item": "md5",
"msg": "$1$P.wul7vX$4L1MTH75XAYb.s9Vg7jy/."
}
ok: [localhost] => (item=sha256) => {
"changed": false,
"item": "sha256",
"msg":
"$5$rounds=535000$m9U3yZOjrvWJGZ4r$kJNaEH23nxRcvu.tMmmxMe7p.BXGemhuy1EYHwzz
F37"
}
ok: [localhost] => (item=sha512) => {
"changed": false,
"item": "sha512",
"msg":
"$6$rounds=656000$kghrt5191Unm3zgj$yuaMqkVfo5uP0qEz3jzaLCvZ57qY26yxaExZw1tA
jX5OyCeTBMYh.cN.KOFqUznOyn/f4xuoMDDs0r7XMLPME."
}
PLAY RECAP **********
localhost : ok=3 changed=0 unreachable=0 failed=0

Filtros de expresiones regulares.


regex_replace Reemplaza texto en una cadena con una
expresión regular.
regex_escape Previene caracteres especiales dentro de una
expresión regular.
regex_search Para buscar una cadena con una expresión
regular.
regex_findall Busca todas las apariciones de coincidencias
de expresiones regulares.
Contenido ejemplo del playbook.
- name: Filtros de expresiones regulares
hosts: localhost
gather_facts: False
tasks:
- name: Filtro regex_replace
debug: msg="{{ item | regex_replace('.j2$','') }}"
with_items:
- plantilla1.j2
- plantilla2.j2
- name: Filtro regex_escape
debug: msg="{{ '^f.*o(.*)$' | regex_escape() }}"

332 © Alfaomega-RC Libros


CAPÍTULO 6: CARACTERÍSTICAS AVANZADAS

- name: Filtro regex_search


debug: msg="{{ item | regex_search('(Debian|CentOS)') }}"
with_items:
- Distro Debian
- Distro CentOS
- name: Filtro regex_findall
debug: msg="{{ 'e4:a4:71:69:07:94' | regex_findall('(..):?') }}"

Resultado de la ejecución.
PLAY [Filtros de expresiones regulares] ****
TASK [Filtro regex_replace] *****************
ok: [localhost] => (item=plantilla1.j2) => {
"changed": false,
"item": "plantilla1.j2",
"msg": "plantilla1"
}
ok: [localhost] => (item=plantilla2.j2) => {
"changed": false,
"item": "plantilla2.j2",
"msg": "plantilla2"
}
TASK [Filtro regex_escape] *****************
ok: [localhost] => {
"msg": "\\^f\\.\\*o\\(\\.\\*\\)\\$"
}
TASK [Filtro regex_search] **
ok: [localhost] => (item=Distro Debian) => {
"changed": false,
"item": "Distro Debian",
"msg": "Debian"
}
ok: [localhost] => (item=Distro CentOS) => {
"changed": false,
"item": "Distro CentOS",
"msg": "CentOS"
}
TASK [Filtro regex_findall] **
ok: [localhost] => {
"msg": [
"e4",
"a4",
"71",
"69",
"07",
"94"

© Alfaomega-RC Libros 333


ANSIBLE

]
}
PLAY RECAP **********
localhost : ok=4 changed=0 unreachable=0 failed=0

Filtros sobre tratado de listas.


random Devuelve un elemento aleatorio de una secuencia
de elementos o genera un número aleatorio.
shuffle Aleatoriza una lista existente, dando un orden
diferente en cada invocación.
union Obtiene una unión de dos listas.
intersect Obtiene la intersección de 2 listas (lista única
de todos los elementos en ambos).
difference Para obtener la diferencia de 2 listas
(elementos en 1 que no existen en 2).
Contenido ejemplo del playbook.
- name: Filtros de tratado de listas
hosts: localhost
gather_facts: False
vars:
usuarios:
- usuario1
- usuario2
- usuario3
- agonzalez
administradores:
- agonzalez
- mperez
tasks:
- name: Mostrar un usuario al azar
debug: msg="{{ usuarios|random }}"
- name: Muestra los usuarios mezclados
debug: msg="{{ usuarios|shuffle }}"
- name: Une dos listas
debug: msg="{{ usuarios|union(administradores) }}"
- name: Muestra los valores que son administradores
debug: msg="{{ usuarios|intersect(administradores) }}"
- name: Muestra los valores que no son administradores
debug: msg="{{ usuarios|difference(administradores) }}"

334 © Alfaomega-RC Libros


CAPÍTULO 6: CARACTERÍSTICAS AVANZADAS

Resultado de la ejecución.
PLAY [Filtros de tratado de listas] *********
TASK [Mostrar un usuario al azar] **********
ok: [localhost] => {
"msg": "usuario3"
}
TASK [Muestra los usuarios mezclados] ***
ok: [localhost] => {
"msg": [
"agonzalez",
"usuario3",
"usuario1",
"usuario2"
]
}
TASK [Une dos listas] ****
ok: [localhost] => {
"msg": [
"usuario1",
"usuario2",
"usuario3",
"agonzalez",
"mperez"
]
}
TASK [Muestra los valores que son administradores] **
ok: [localhost] => {
"msg": [
"agonzalez"
]
}
TASK [Muestra los valores que no son administradores]
***************
ok: [localhost] => {
"msg": [
"usuario1",
"usuario2",
"usuario3"
]
}
PLAY RECAP **********
localhost : ok=5 changed=0 unreachable=0 failed=0

© Alfaomega-RC Libros 335


ANSIBLE

Filtros de funciones matemáticas.


log Obtiene el logratimo.
pow Potencia de n,
root Raiz cuadrada o raiz.
Contenido ejemplo del playbook.
- name: Filtros matemáticos
hosts: localhost
gather_facts: False
tasks:
- name: Mostrar logaritmo de 2
debug: msg="{{ 2 | log }}"
- name: Mostrar 2 al cubo
debug: msg="{{ 2 | pow(3) }}"
- name: Mostrar raiz cuadrada de 16
debug: msg="{{ 16 | root }}"
Resultado de la ejecución.
PLAY [Filtros matemáticos] **
TASK [Mostrar logaritmo de 2] **************
ok: [localhost] => {
"msg": "0.69314718056"
}
TASK [Mostrar 2 al cubo] ****
ok: [localhost] => {
"msg": "8.0"
}
TASK [Mostrar raíz cuadrada de 16] ********
ok: [localhost] => {
"msg": "4.0"
}
PLAY RECAP **********
localhost : ok=3 changed=0 unreachable=0 failed=0

Filtros de utilidades de red.


ipaddr ipaddr(value, query = '', version = False, alias
= 'ipaddr')
Devuelve el valor de entrada si una consulta es
True y False si la consulta es False.
ipsubnet Se puede usar para manipular subredes de red de
varias maneras.

336 © Alfaomega-RC Libros


CAPÍTULO 6: CARACTERÍSTICAS AVANZADAS

hwaddr Puede usar el filtro hwaddr para verificar si una


cadena dada es una dirección MAC o convertirla
entre varios formatos.
ipv4 Comprueba si una cadena es una dirección IPv4
válida.
ipv6 Comprueba si una cadena es una dirección IPv6
válida.
Contenido ejemplo del playbook.
- name: Filtros de utilidades red
hosts: localhost
gather_facts: False
tasks:
- name: Comprobar si es ip correcta
debug: msg="{{ item | ipv4 }}"
with_items:
- 192.168.100.2
- 192.168.100.2/16
- 192.168.300.2
- name: Obtener IP de un CIDR
debug: msg="{{ '2a02:8109:b180:66d0:e6a4:71ff:fe69:794/64'|ipaddr('address') }}"
- name: Obtener red de un CIDR
debug: msg="{{ '192.168.100.2/16' | ipaddr('network') }}"
- name: Obtener netmask de un CIDR
debug: msg="{{ '192.168.100.2/16' | ipv4('netmask') }}"
- name: Obtener broadcast de un CIDR
debug: msg="{{ '192.168.100.2/16' | ipv4('broadcast') }}"
- name: Obtener prefijo de un CIDR
debug: msg="{{ '2001:db8::/32' | ipv6('prefix') }}"
- name: Convertir a CIDR
debug: msg="{{ '192.168.0.0/255.255.255.0'|ipaddr('net') }}"
- name: Comprobar si es red correcta
debug: msg="{{ item | ipsubnet }}"
with_items:
- 192.168.100.2/16
- 192.168.100.2/33
- name: Convertir mac a formato cisco
debug: msg="{{ '52:54:00:3a:7d:47' | hwaddr('cisco') }}"
Resultado de la ejecución.
PLAY [Filtros de utilidades red] *************
TASK [Comprobar si es ip correcta] ********
ok: [localhost] => (item=192.168.100.2) => {
"changed": false,

© Alfaomega-RC Libros 337


ANSIBLE

"item": "192.168.100.2",
"msg": "192.168.100.2"
}
ok: [localhost] => (item=192.168.100.2/16) => {
"changed": false,
"item": "192.168.100.2/16",
"msg": "192.168.100.2/16"
}
ok: [localhost] => (item=192.168.300.2) => {
"changed": false,
"item": "192.168.300.2",
"msg": false
}
TASK [Obtener IP de un CIDR] *************
ok: [localhost] => {
"msg": "2a02:8109:b180:66d0:e6a4:71ff:fe69:794"
}
TASK [Obtener red de un CIDR] ************
ok: [localhost] => {
"msg": "192.168.0.0"
}
TASK [Obtener netmask de un CIDR] ******
ok: [localhost] => {
"msg": "255.255.0.0"
}
TASK [Obtener broadcast de un CIDR] ****
ok: [localhost] => {
"msg": "192.168.255.255"
}
TASK [Obtener prefijo de un CIDR] *********
ok: [localhost] => {
"msg": "32"
}
TASK [Convertir a CIDR] ****
ok: [localhost] => {
"msg": "192.168.0.0/24"
}
TASK [Comprobar si es red correcta] *******
ok: [localhost] => (item=192.168.100.2/16) => {
"changed": false,
"item": "192.168.100.2/16",
"msg": "192.168.100.2/16"
}
ok: [localhost] => (item=192.168.100.2/33) => {
"changed": false,

338 © Alfaomega-RC Libros


CAPÍTULO 6: CARACTERÍSTICAS AVANZADAS

"item": "192.168.100.2/33",
"msg": false
}
TASK [Convertir mac a formato cisco] ******
ok: [localhost] => {
"msg": "5254.003a.7d47"
}
PLAY RECAP **********
localhost : ok=9 changed=0 unreachable=0 failed=0

Filtros de utilidades varias.


mandatory Obliga que una variable esté definida.
bool Verifica si el valor es un booleano.
quote Añade citas para el uso de Shell.
ternary Usa un valor en verdadero y otro en falso.
version_compare Para comparar un número de versión.
comment El filtro de comentarios permite decorar el
texto con un estilo de comentario elegido.
Contenido ejemplo del playbook.
- name: Filtros de utilidades varias.
hosts: localhost
gather_facts: False
vars:
existe: "Libro Ansible"
fichero: 'usuarios "admin".txt'
tipo: admin
tasks:
- name: Valor de la variable o falla si no está definida
debug: msg="{{ existe | mandatory }}"
- name: Comprueba si la variable es de tipo boolean
debug: msg="{{ existe | bool }}"
- name: Entrecomilla una cadena de texto para shell
debug: msg="{{ fichero | quote }}"
- name: Muestra uno u otro valor según la condición
debug: msg="{{ (tipo=="admin") | ternary('Usuario
administrador', 'Usuario normal') }}"
- name: Cambiar el tipo
set_fact: tipo="usuario"
- name: Muestra uno u otro valor según la condición
debug: msg="{{ (tipo=="admin") | ternary('Usuario
administrador', 'Usuario normal') }}"

© Alfaomega-RC Libros 339


ANSIBLE

- name: Falla porque no existe


debug: "{{ no_existe | mandatory }}"
Resultado de la ejecución.
PLAY [Filtros de utilidades varias.] *********
TASK [Muestra el valor de la variable o falla si no está
definida] ***************
ok: [localhost] => {
"msg": "Libro Ansible"
}
TASK [Comprueba si la variable es de tipo boolean]
*************
ok: [localhost] => {
"msg": false
}
TASK [Entrecomilla una cadena de texto para usar con shell]
ok: [localhost] => {
"msg": "'usuarios \"admin\".txt'"
}
TASK [Muestra uno u otro valor dependiendo de la condición]
ok: [localhost] => {
"msg": "Usuario administrador"
}
TASK [Cambiar el tipo] ***
ok: [localhost]
TASK [Muestra uno u otro valor dependiendo de la condición]
ok: [localhost] => {
"msg": "Usuario normal"
}
TASK [Falla porque no existe] ***************
fatal: [localhost]: FAILED! => {"msg": "Mandatory variable
not defined."}
to retry, use: --limit @/tmp/filtros_varios.retry
PLAY RECAP **********
localhost : ok=6 changed=0 unreachable=0 failed=1

Otros filtros proporcionados por Jinja2 son los siguientes:


Filtro Descripción Ejemplos
abs Devuelve el {{ -1 | abs }} = 1
valor absoluto
del argumento.
capitalize Capitaliza un {{ "libro" | capitalize }} = Libro
valor.

340 © Alfaomega-RC Libros


CAPÍTULO 6: CARACTERÍSTICAS AVANZADAS

default Si el valor no {{ "libro" | default("algo") }} = libro


está definido, {{ no_existe | default(1) }} = 1
devolverá el
valor
predeterminado
aprobado, de lo
contrario, el
valor de la
variable.
dictsort Clasifica un Ver ejemplo específico.
dict y rienda
(clave, valor)
pares.
escape Convierte los {{ "<>" | escape }} = &lt;&gt;
caracteres &,
<,>, ', y "en
cadena s en
secuencias
seguras para
HTML.
filesizeformat Formatea el {{ 4096000|filesizeformat }} = 4.1 MB
valor como un
tamaño de
archivo 'legible
para humanos'.
first Devuelve el {{ [3,14,16]|first }} = 3
primer elemento
de una
secuencia.
float Convierta el {{ "4.3"|float }} = 4.13
valor en un
número de punto
flotante.
format Aplica formato {{ %s-%d|format("num", 3) }} = "num-3"
de cadena de
python en un
objeto:
groupby Agrupa una Ver ejemplo específico.
secuencia de
objetos por un
atributo común.

© Alfaomega-RC Libros 341


ANSIBLE

int Convierte el {{ 3.14 | int }} = 3


valor en un
entero.
join Devuelve una {{ [3,14,16] | join("-") } = 3-14-16
cadena que es la
concatenación de
las cadenas en
la secuencia.
last Devuelve el {{ [3,14,16] | last }} = 16
último elemento
de una
secuencia.
length Devuelve el {{ [3,14,16] | length }} = 3{{ "libro" |
número de length }} =5
elementos de una
secuencia o
mapeo.
list Convierte el {{ "libro" | list }} = ['l','i','b','r','o']
valor en una
list
lower Convierte un {{ "LIBRO" | lower }} = "libro"
valor a
minúscula.
map Aplica un filtro Ver ejemplo específico.
en una secuencia
de objetos o
busca un
atributo.
max Devuelve el {{ [3,24,16] | max }} = 24
objeto más
grande de la
secuencia.
min Devuelve el {{ [3,24,16] | min }} = 3
objeto más
pequeño de la
secuencia.
replace Devuelve una {{ "libro chef"|replace("chef", "ansible")
copia del valor }} = "libro ansible"
con todas las
ocurrencias de
una subcadena

342 © Alfaomega-RC Libros


CAPÍTULO 6: CARACTERÍSTICAS AVANZADAS

reemplazada por
una nueva.
reverse Invierte el {{ [3,24,16] | reverse|list }} = [16,24,3]
objeto o {{ "libro" | reverse }} = "orbil"
devuelve un
iterador que lo
repite al revés.
round Redondea el {{ 3.14 | round }} = 3.0
número a una {{ 3.14 | round(method="ceil") }} = 4.0
precisión dada. {{ 3.80 | round(method="floor") }} = 3.0

select Filtra una Ver ejemplo específico.


secuencia de
objetos
aplicando una
prueba a cada
objeto, y solo
seleccionando
los objetos con
la prueba
exitosa.
selectattr Filtra una Ver ejemplo específico.
secuencia de
objetos
aplicando una
prueba al
atributo
especificado de
cada objeto, y
solo
seleccionando
los objetos con
la prueba
exitosa.
sort Ordena un {{ [3,24,16] | sort }} = [3,16,24]
iterable. Por
defecto, ordena
ascendente.
string Hace un unicode {{ 4 | string }} = "4"
de cadena si no
está ya.
sum Devuelve la suma {{ [3,24,16] | sum }} = 43
de una secuencia

© Alfaomega-RC Libros 343


ANSIBLE

trim Despliegue del {{ " libro " | trim }} = "libro"


espacio en
blanco inicial y
posterior.
truncate Devuelve una {{ "libro" | truncate(3,end='') }} = "lib"
copia truncada
de la cadena.
unique Devuelve una {{ [3,24,16,3,24] | unique }} = [3,24,16]
lista de
elementos únicos
del iterable
dado.
upper Convierte un {{ "libro" | lower }} = "LIBRO"
valor a
mayúsculas.
wordcount Cuenta las {{ "libro ansible"|wordcount }}=2
palabras en esa
cadena.

Ejemplos con funciones más avanzadas:

Filtro dictsort. Contenido del playbook.


- name: Ordenar el contenido de un diccionario.
hosts: localhost
gather_facts: False
vars:
usuarios:
jveipen:
nombre: Jonathan
apellido: Veites
email: jveipen@oforte.net
agonzalez:
nombre: Alberto
apellido: Gonzalez
email: alberto@oforte.net
tasks:
- debug: msg="{{ usuarios|dictsort }}"
Salida del playbook (todas las claves están ordenadas por
orden alfabético).
ok: [localhost] => {
"msg": [

344 © Alfaomega-RC Libros


CAPÍTULO 6: CARACTERÍSTICAS AVANZADAS

[
"agonzalez",
{
"apellido": "Gonzalez",
"email": "alberto@oforte.net",
"nombre": "Alberto"
}
],
[
"jveipen",
{
"apellido": "Veites",
"email": "jveipen@oforte.net",
"nombre": "Jonathan"
}
]
]

Filtro groupby. Contenido del playbook.


- name: Agrupar por género y mostrar los usuarios de cada uno de ellos.
hosts: localhost
gather_facts: False
vars:
usuarios:
- nombre: jveipen
genero: masculino
- nombre: agonzalez
genero: masculino
- nombre: mperez
genero: femenino
tasks:
- set_fact: contenido="{{ lookup('template','generos.j2') }}"
- copy:
dest: /tmp/generos.txt
content: "{{ contenido }}"
Plantilla generos.j2
{% for genero, lista in usuarios|groupby('genero') %}
Genero: {{ genero }}
{% for usuario in lista %}
Usuario: {{ usuario.nombre }}
{% endfor %}
{% endfor %}

© Alfaomega-RC Libros 345


ANSIBLE

Resultado
Genero: femenino
Usuario: mperez
Genero: masculino
Usuario: jveipen
Usuario: agonzalez

Filtro map. Contenido del playbook.


- name: Mostrar solo el atributo 'login'
hosts: localhost
gather_facts: False
vars:
usuarios:
- nombre: Jonathan
apellido: Veites
email: jveipen@oforte.net
login: jveipen
- nombre: Alberto
apellido: Gonzalez
email: alberto@oforte.net
login: agonzalez
tasks:
- debug: msg=" {{ usuarios|map(attribute='login') | list }}"
Resultado mostrado.
ok: [localhost] => {
"msg": [
"jveipen",
"agonzalez"
]
}

Filtro select. Contenido del playbook.


- name: Comprobar si un usuario existe y mostrar n. impares
hosts: localhost
gather_facts: False
vars:
usuarios:
- jveipen
- agonzalez

346 © Alfaomega-RC Libros


CAPÍTULO 6: CARACTERÍSTICAS AVANZADAS

- mperez
ids:
- 1
- 2
- 3
tasks:
- debug: msg="{{ usuarios|select("equalto", 'agonzalez')
| list | length }}"
- debug: msg="{{ ids|select('odd') | list }}"
Salida de la ejecución.
TASK [debug] **********
ok: [localhost] => {
"msg": "1"
}
TASK [debug] **********
ok: [localhost] => {
"msg": [
1,
3
]
}

Filtro selectattr. Contenido del playbook.


- name: Buscar usuarios por un atributo
hosts: localhost
gather_facts: False
vars:
usuarios:
- nombre: Jonathan
apellido: Veites
email: jveipen@oforte.net
login: jveipen
- nombre: Alberto
apellido: Gonzalez
email: alberto@oforte.net
login: agonzalez
tasks:
- debug: msg="{{ usuarios|selectattr('email','equalto',
'alberto@oforte.net') | list }}"
Resultado de la ejecución.
ok: [localhost] => {
"msg": [

© Alfaomega-RC Libros 347


ANSIBLE

{
"apellido": "Gonzalez",
"email": "alberto@oforte.net",
"login": "agonzalez",
"nombre": "Alberto"
}
]
}

VAULT

Vault es una característica de Ansible que permite alojar datos confidenciales


(contraseñas, códigos, etc.) en ficheros cifrados para evitar que esos datos estén
disponibles en texto claro dentro del Playbook.

ANSIBLE-VAULT

El comando para administrar ficheros que contiene información cifrada con


Vault se llama ansible-vault.

La sintaxis es la siguiente:

ansible-vault comando fichero.yml

Donde los comandos posibles son los siguientes:

create

Permite crear un nuevo fichero cifrado, donde alojaremos la información a


cifrar. Una vez ejecutado el comando, primero solicitará una contraseña para
cifrar el fichero y a posteriori se abrirá el editor de texto por defecto definido en el
sistema.

# ansible-vault create secreto.yml


New Vault password:
Confirm New Vault password:
Contenido ejemplo
clave: l1br04ns1bl3

348 © Alfaomega-RC Libros


CAPÍTULO 6: CARACTERÍSTICAS AVANZADAS

Comprobar que el fichero está cifrado.


# cat secreto.yml
$ANSIBLE_VAULT;1.1;AES256
35303061306537663838303532653865626662306466643331373235636438313136616631656133
6266663365393735363431616165363834363461636236310a366439316165313530386462653332
38333165383332306164366436306235313963363831613435363165373538343966663136373762
3936336436626435370a313366373231333138346137306664316631343566656433333330323530
37663837373035313663353734393262376333626665386234343664383964616533

edit

Permite editar un fichero cifrado previamente con Vault. Solicitará la


contraseña usada para cifrarlo y se abrirá un editor de texto.

# ansible-vault edit secreto.yml


Vault password:

encrypt

Permite cifrar un fichero que anteriormente no estaba cifrado. Se solicitará la


contraseña para proteger el fichero.

Contenido del fichero antes de cifrarlo.


# cat secreto2.yml
clave: l1br04ns1bl3
Cifrado del fichero.
# ansible-vault encrypt secreto2.yml
New Vault password:
Confirm New Vault password:
Encryption successful
Comprobar cifrado.
# cat secreto2.yml
$ANSIBLE_VAULT;1.1;AES256
66366239313965343632643238613632383930653533643735366538616465373565383362323563
3565623065663863383339613466393437616364643630610a323438396432356638616565376338
35303033303632353431636163363235336532326239633833303861386631626232656634356564
3736346237393037370a333463356138663134383935356332636436346338336262323237643062
65663335313530363339373438396437323064356333316636383837326135353465

© Alfaomega-RC Libros 349


ANSIBLE

decrypt

Permite descifrar un fichero que anteriormente estaba cifrado. Se solicitará la


contraseña para desproteger el fichero.

Comprobar cifrado.
# cat secreto2.yml
$ANSIBLE_VAULT;1.1;AES256
66366239313965343632643238613632383930653533643735366538616465373565383362323563
3565623065663863383339613466393437616364643630610a323438396432356638616565376338
35303033303632353431636163363235336532326239633833303861386631626232656634356564
3736346237393037370a333463356138663134383935356332636436346338336262323237643062
65663335313530363339373438396437323064356333316636383837326135353465

Descifrar fichero.
# ansible-vault decrypt secreto2.yml
Vault password:
Decryption successful
# cat secreto2.yml
clave: l1br04ns1bl3

rekey

Permite cambiar la contraseña de un fichero que anteriormente estaba


cifrado.

# ansible-vault rekey secreto.yml


Vault password:
New Vault password:
Confirm New Vault password:
Rekey successful

view

Permite ver el contenido de un fichero cifrado. Se solicitará la contraseña para


mostrar el contenido.

# ansible-vault view secreto.yml


Vault password:
clave: l1br04ns1bl3

350 © Alfaomega-RC Libros


CAPÍTULO 6: CARACTERÍSTICAS AVANZADAS

ANSIBLE-PLAYBOOK

El comando ansible-playbook contiene dos opciones para indicar la contraseña


a ser utilizada para descifrar los ficheros:

Ansible >=2.4 Ansible <2.4 Descripción


--vauit-id @prompt --ask-vault-pass Esta opción solicitará al
usuario que ejecuta el
comando por la contraseña
para descifrar los
ficheros que están
cifrados.
--vault-id=fichero --vault-password-file=fic Indica un fichero que
contiene la contraseña a
ser utilizada para
descifrar.

En el siguiente ejemplo se muestra el uso de dichas opciones para utilizar las


variables en ficheros cifrados.

Contenido del playbook ejemplo.


- name: Ejemplo de uso de Vault
hosts: localhost
tasks:
- include_vars: secreto.yml
- debug: var=clave
Resultado al ejecutar el playbook sin indicar la contraseña
de Vault.
# ansible-playbook vault.yml
PLAY [Ejemplo de uso de Vault] *************
TASK [include_vars] ***
fatal: [localhost]: FAILED! => {"ansible_facts": {},
"ansible_included_var_files": [], "changed": false,
"message": "Attempting to decrypt but no vault secrets
found"}
to retry, use: --limit @/root/playbooks/vault/vault.retry

PLAY RECAP **********


localhost : ok=0 changed=0 unreachable=0 failed=1

© Alfaomega-RC Libros 351


ANSIBLE

Solicitando la contraseña al usuario.


# ansible-playbook --vault-id @prompt vault.yml
Vault password:
PLAY [Ejemplo de uso de Vault] ***************
TASK [include_vars] ***
ok: [localhost]
TASK [debug] **********
ok: [localhost] => {
"clave": "l1br04ns1bl3"
}
PLAY RECAP ************
localhost : ok=2 changed=0 unreachable=0 failed=0
Ejecutar playbook utilizando un fichero que contiene la
contraseña para descifrar.
# echo "clavesecreta" > /root/clave.vault
# ansible-playbook --vault-id=/root/clave.vault vault.yml
PLAY [Ejemplo de uso de Vault] *************
TASK [include_vars] ***
ok: [localhost]
TASK [debug] **********
ok: [localhost] => {
"clave": "l1br04ns1bl3"
}
PLAY RECAP **********
localhost : ok=2 changed=0 unreachable=0 failed=0

TAREAS ASÍNCRONAS
Cuando se realiza una tarea en un nodo, a través de un módulo, la conexión
permanece abierta esperando a que la acción finalice. En tareas que requieran
tiempo largo de ejecución, puede causar problemas de que la conexión se cierre
por inactividad. Ansible nos da la opción de realizar una tarea en segundo plano y
comprobar su estado periódicamente sin tener que permanecer la conexión
abierta.

Para ello utilizaremos los argumentos async (tiempo máximo a esperar que
una aplicación termine) y poll (la periodicidad en segundos de la comprobación
del estado de la tarea). En el siguiente ejemplo se ejecuta un comando que
tardará 60 segundos en finalizar (comando sleep), con async se esperará un
máximo de 90 segundos y se comprobará con poll cada 5 segundos.

352 © Alfaomega-RC Libros


CAPÍTULO 6: CARACTERÍSTICAS AVANZADAS

Contenido del playbook.


- name: Esperar a que una tarea larga finalice
hosts: www
gather_facts: False
tasks:
- command: /bin/sleep 60
async: 90
poll: 5

Comprobación en el nodo remoto (usando journalctl).

Apr 14 12:57:28 www ansible-async_status[18782]: Invoked with jid=713492296415.18621


mode=status
Apr 14 12:57:33 www ansible-async_wrapper.py[18624]: 18625 still running (45)
Apr 14 12:57:34 www ansible-async_status[18799]: Invoked with jid=713492296415.18621
mode=status
Apr 14 12:57:38 www ansible-async_wrapper.py[18624]: 18625 still running (40)
Apr 14 12:57:39 www ansible-async_status[18816]: Invoked with jid=713492296415.18621
mode=status
Apr 14 12:57:43 www ansible-async_wrapper.py[18624]: 18625 still running (35)
Apr 14 12:57:43 www ansible-async_wrapper.py[18625]: Module complete (18625)
Apr 14 12:57:45 www ansible-async_status[18833]: Invoked with jid=713492296415.18621
mode=status
Apr 14 12:57:48 www ansible-async_wrapper.py[18624]: Done in kid B.

Ansible también nos permite ejecutar una tarea en segundo plano sin esperar
(usando poll con valor 0), realizar distintas tareas y a posteriori comprobar en otra
tarea el estado de la ejecutada en segundo plano utilizando el módulo
async_status. A continuación se muestra un ejemplo.

Contenido del playbook.


- name: Esperar a que una tarea larga finalice
hosts: www
tasks:
- name: Primera tarea
command: /bin/sleep 60
async: 90
poll: 0
register: estado_sleep
- name: Segundatarea
debug: var=ansible_fqdn

© Alfaomega-RC Libros 353


ANSIBLE

- name: Esperar por la primera tarea


async_status:
jid: "{{ estado_sleep.ansible_job_id }}"
register: comprobar_estado_sleep
until: comprobar_estado_sleep.finished
retries: 9
delay: 10
Resultado de la ejecución.
PLAY [Esperar a que una tarea larga finalice] ********************
TASK [Gathering Facts] **
ok: [www]
TASK [Primera tarea] **
changed: [www]
TASK [Segundatarea] ****
ok: [www] => {
"ansible_fqdn": "www"
}
TASK [Esperar por la primera tarea] ********
FAILED - RETRYING: Esperar por la primera tarea (9 retries left).
FAILED - RETRYING: Esperar por la primera tarea (8 retries left).
FAILED - RETRYING: Esperar por la primera tarea (7 retries left).
FAILED - RETRYING: Esperar por la primera tarea (6 retries left).
FAILED - RETRYING: Esperar por la primera tarea (5 retries left).
FAILED - RETRYING: Esperar por la primera tarea (4 retries left).
changed: [www]
PLAY RECAP *********
www : ok=4 changed=2 unreachable=0 failed=0

Es posible utilizar "pool: 0" para ejecutar una tarea sin importanos el
resultado de la tarea, se denomina fire and forget (disparar y olvidar).

- name: fire and forget


hosts: servidor
tasks:
- name: Ejecutar tarea sin preocuparnos cuándo termine
command: /bin/sleep 3600
async: 1
poll: 0

354 © Alfaomega-RC Libros


CAPÍTULO 6: CARACTERÍSTICAS AVANZADAS

OPCIONES AVANZADAS
Hay opciones avanzadas para configurar el funcionamiento de un
Playbook/Rol/Block/Tarea. Se muestran a continuación:

any_errors_fatal Fuerza que una tarea fallida en un nodo


marque todos los nodos como fallidos.
diff Muestra los cambios en formato diff
realizados por template.
force_handlers Fuerza la ejecución de los handlers
incluso si una tarea ha fallado.
max_fail_percentage Porcentaje de nodos que al ser alcanzado
por tareas fallidas, para marcar todo el
playbook como fallido.
no_log No muestra la salida del comando
(incluso con -vvv) para proteger
información.
serial Indica cuántos nodos en paralelo
procesarán tareas.

Las siguientes opciones son usadas para tareas:

run_once=True/False Utilizado para ejecutar la tarea


en sólo uno de los nodos. Por
ejemplo si se está instalando un
cluster de base de datos y es
necesario importar una base de
datos, realizarlo solo en uno.
delegate_facts=True/False Delegar los facts al utilizar
delegate_to.

En el siguiente ejemplo utilizamos any_errors_fatal para detener la ejecución


del Playbook en caso de que uno nodo falle. El comportamiento por defecto es
continuar la ejecución en los nodos que no ha fallado:

Contenido del playbook.


- name: Ejemplo de any_errors_fatal
hosts: all
gather_facts: False

© Alfaomega-RC Libros 355


ANSIBLE

any_errors_fatal: True
tasks:
- name: Tarea que falla en un nodo
command: dpkg --version
- name: Debería ejecutarse en los que no ha fallado
command: dpkg -l
Salida de la ejecución.
PLAY [Ejemplo de any_errors_fatal] ********
TASK [Tarea que falla en un nodo] *********
changed: [ansible01]
changed: [debian01]
fatal: [centos01]: FAILED! => {"changed": false, "cmd":
"dpkg --version", "msg": "[Errno 2] No such file or
directory", "rc": 2}
NO MORE HOSTS LEFT ***
to retry, use: --limit @/root/playbooks/avanzado.retry

PLAY RECAP **********


ansible01 : ok=1 changed=1 unreachable=0 failed=0
centos01 : ok=0 changed=0 unreachable=0 failed=1
debian01 : ok=1 changed=1 unreachable=0 failed=0

En el siguiente ejemplo en una tarea se activa la opción no_log:

Contenido del playbook.


- name: Ejemplo de no_log
hosts: localhost
gather_facts: False
tasks:
- include_vars: vault/secreto.yml
no_log: True
- name: Tarea que muestra una clave
command: echo "{{ clave }}"
- name: Tarea que no muestra una clave
command: echo "{{ clave }}"
no_log: True
Resultado de la ejecución.
PLAY [Ejemplo de no_log] ***
META: ran handlers
TASK [include_vars] ***
task path: /root/playbooks/avanzado2.yml:5
ok: [localhost] => {"censored": "the output has been hidden due to the

356 © Alfaomega-RC Libros


CAPÍTULO 6: CARACTERÍSTICAS AVANZADAS

fact that 'no_log: true' was specified for this result"}


TASK [Tarea que muestra una clave] *******
task path: /root/playbooks/avanzado2.yml:8
changed: [localhost] => {"changed": true, "cmd": ["echo", "l1br04ns1bl3"],
"delta": "0:00:00.025181", "end": "2018-04-14 13:49:29.538163", "rc": 0,
"start": "2018-04-14 13:49:29.512982", "stderr": "", "stderr_lines": [],
"stdout": "l1br04ns1bl3", "stdout_lines": ["l1br04ns1bl3"]}
TASK [Tarea que no muestra una clave] ***
task path: /root/playbooks/avanzado2.yml:11
ok: [localhost] => {"censored": "the output has been hidden due to the
fact that 'no_log: true' was specified for this result"}

PLAY RECAP **********


localhost : ok=3 changed=2 unreachable=0 failed=0

EXTENDER ANSIBLE
Ansible nos da la opción de desarrollar nuestros propios filtros y módulos para
extender la funcionalidad que nos proporciona por defecto. Es recomendado
tener conocimientos previos de Python para ello.

LOOKUP

A continuación se muestra un ejemplo con la estructura básica para crear un


lookup, el directorio para nuestros propios lookup es lookup_plugins/ al mismo
nivel que el Playbook.

lookup_plugins/whoami.py
# python 3 headers, required if submitting to Ansible
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = """
lookup: whoami
author: Alberto Gonzalez <alberto@oforte.net>
version_added: "0.1"
short_description: Devuelve el usuario que ejecuta el playbook
description:
- Este lookup devuelve el usuario que ejecuta el playbook
"""
from ansible.errors import AnsibleError, AnsibleParserError
from ansible.plugins.lookup import LookupBase
try:

© Alfaomega-RC Libros 357


ANSIBLE

from __main__ import display


except ImportError:
from ansible.utils.display import Display
display = Display()
class LookupModule(LookupBase):
def run(self, terms, variables=None, **kwargs):
from subprocess import check_output
ret = check_output(["whoami"])
return [ret]
Playbook ejemplo.
- hosts: servidor
gather_facts: False
tasks:
- name: Mostrar usuario actual
debug: msg="{{ lookup('whoami') }}"
Resultado de la ejecución.
# whoami
root
# ansible-playbook whoami.yml
PLAY [servidor] ******
TASK [Mostrar usuario actual] ***************
ok: [servidor] => {
"msg": "root\n"
}
PLAY RECAP ************

FILTROS

A continuación se muestra un ejemplo con la estructura básica para crear un


filtro. El directorio para nuestros propios filtros es filter_plugins/ al mismo nivel
que el Playbook. En este ejemplo se cifra una cadena de forma básica con rot13.
Contenido filter_plugins/cifrar.py.
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
from ansible.errors import AnsibleError, AnsibleFilterError
def rot13(data):
import codecs
return codecs.encode(data, 'rot_13')
class FilterModule(object):
''' Cifrar con rot13 '''
def filters(self):

358 © Alfaomega-RC Libros


CAPÍTULO 6: CARACTERÍSTICAS AVANZADAS

return {
'cifrar': rot13,
}
Contenido del playbook.
- hosts: localhost
gather_facts: False
tasks:
- debug: msg="{{ 'ejemplo' | cifrar }}"
Resultado de la ejecución.
ok: [localhost] => {
"msg": "rwrzcyb"
}

MÓDULOS

A continuación se muestra un ejemplo con la estructura básica para crear un


módulo, el directorio para nuestros propios módulos es library/ al mismo nivel que
el Playbook.
Contenido library/sumar.py.
#!/usr/bin/python
ANSIBLE_METADATA = {
'metadata_version': '0.1',
'status': ['preview'],
'supported_by': 'community'
}
DOCUMENTATION = '''
---
module: sumar
short_description: Suma dos numeros
options:
a:
description:
- Primer numero
required: true
b:
description:
- Segundo numero
required: true
author:
- Alberto Gonzalez <alberto@oforte.net>
'''

© Alfaomega-RC Libros 359


ANSIBLE

EXAMPLES = '''
- name: Suma 2 + 3
sumar:
a: 2
b: 3
'''
from ansible.module_utils.basic import AnsibleModule
def run_module():
module_args = dict(
a=dict(type='int', required=True),
b=dict(type='int', required=True)
)
result = dict(
changed=False,
resultado=''
)
module = AnsibleModule(
argument_spec=module_args,
supports_check_mode=True
)
result['resultado'] = module.params['a']+module.params['b']
module.exit_json(**result)

def main():
run_module()

if __name__ == '__main__':
main()
Contenido del playbook.

- hosts: localhost
gather_facts: False
tasks:
- sumar:
a: 2
b: 3
register: suma
- debug: var=suma.resultado
Resultado de la ejecución.

TASK [debug] **********


ok: [localhost] => {
"suma.resultado": "5"
}

360 © Alfaomega-RC Libros


CAPÍTULO 6: CARACTERÍSTICAS AVANZADAS

INVENTARIO

A continuación se muestra un ejemplo con la estructura básica para crear un


script de inventario personalizado. El script tiene que aceptar las opciones --list y –
host, devolviendo el contenido en JSON.

Contenido del script.


#!/usr/bin/env python
from subprocess import Popen, PIPE
import sys
import json

result = {}
result['all'] = {}

pipe = Popen(['listar', 'servidores', '-ip'], stdout=PIPE,


universal_newlines=True)
result['all']['hosts'] = []
for l in pipe.stdout.readlines():
s = l.split(':')
if s[1] != 'global':
result['all']['hosts'].append(s[1])
result['all']['vars'] = {}
result['all']['vars']['ansible_connection'] = 'ssh'
if len(sys.argv) == 2 and sys.argv[1] == '--list':
print(json.dumps(result))
elif len(sys.argv) == 3 and sys.argv[1] == '--host':
print(json.dumps({'ansible_connection': ssh}))
else:
sys.stderr.write("Necesita un argumento, --list o --host
<host>\n")

Bucles avanzados
Es posible realizar bucles sobre elementos distintos a listas y diccionarios. En la
siguiente tabla se muestran los elementos que se pueden recorrer y la sintaxis a
utilizar.

with_file Itera sobre el contenido de uno o varios ficheros.


with_fileglob Devuelve lista de ficheros que concuerde con un patrón,
pero no de forma recursiva.

© Alfaomega-RC Libros 361


ANSIBLE

with_filetree Devuelve una lista de ficheros que concuerde con un


patrón, de forma recursiva.
with_together Recorre dos listas de forma paralela.
with_sequence Recorre una secuencia de números enteros.
with_random_choice Elige un elemento aleatorio de una lista.

A continuación se muestra ejemplo de cada uno de ellos.

Playbook ejemplo con with_file.


- name: Ejemplo con with_file
hosts: servidor
gather_facts: False
tasks:
- debug: msg="{{ item }}"
with_file:
- /etc/hostname
- /etc/resolv.conf
Resultado ejemplo with_file.
TASK [debug]
ok: [servidor] => (item=None) => {
"msg": "cloud.oforte.net"
}
ok: [servidor] => (item=None) => {
"msg": "nameserver 213.186.33.99\nnameserver
10.10.10.6\nsearch ovh.net"
}
Playbook ejemplo con with_fileglob.
- name: Ejemplo con with_fileglob
hosts: servidor
gather_facts: False
tasks:
- debug: msg="{{ item }}"
with_fileglob: "/etc/m*.conf"
Resultado ejemplo with_fileglob.
TASK [debug]
ok: [servidor] => (item=None) => {
"msg": "/etc/mongodb.conf"
}
ok: [servidor] => (item=None) => {

362 © Alfaomega-RC Libros


CAPÍTULO 6: CARACTERÍSTICAS AVANZADAS

"msg": "/etc/mke2fs.conf"
}
Playbook ejemplo con with_filetree.
- name: Ejemplo con with_filetree
hosts: servidor
gather_facts: False
tasks:
- debug: msg="{{ item.src }}"
when: item.state == 'file'
with_filetree: "/etc/supervisor"
Resultado ejemplo with_fileglob.
TASK [debug]
skipping: [servidor] => (item=None)
ok: [servidor] => (item=None) => {
"msg": "/etc/supervisor/supervisord.conf"
}
ok: [servidor] => (item=None) => {
"msg": "/etc/supervisor/conf.d/long_script.conf"
}
Playbook ejemplo con with_together.

- name: Ejemplo con with_together


hosts: servidor
gather_facts: False
vars:
letras: ['a', 'b', 'c']
codigo_ascii: [97, 98, 99]
tasks:
- debug: msg="{{ item.0 }}={{ item.1 }}"
with_together:
- "{{ letras }}"
- "{{ codigo_ascii }}"
Resultado ejemplo with_together.

TASK [debug]
ok: [servidor] => (item=None) => {
"msg": "a=97"
}
ok: [servidor] => (item=None) => {
"msg": "b=98"
}
ok: [servidor] => (item=None) => {

© Alfaomega-RC Libros 363


ANSIBLE

"msg": "c=99"
}
Playbook ejemplo con with_sequence.

- name: Ejemplo con with_sequence


hosts: servidor
gather_facts: False
tasks:
- debug: msg="{{ item }}"
with_sequence: start=1 end=9 stride=3
Resultado ejemplo with_sequence.
TASK [debug]
ok: [servidor] => (item=None) => {
"msg": "1"
}
ok: [servidor] => (item=None) => {
"msg": "4"
}
ok: [servidor] => (item=None) => {
"msg": "7"
}
Playbook ejemplo con with_random_choice.
- name: Ejemplo con with_sequence
hosts: servidor
gather_facts: False
tasks:
- debug: msg="{{ item }}"
with_random_choice:
- "libro"
- "ansible"
- "ejemplo"
Resultado ejemplo with_random_choice.
TASK [debug]
ok: [servidor] => (item=None) => {
"msg": "ansible"
}

Local facts
El módulo setup obtiene facts con información del sistema, como uso de
memoria, interfaces de red, discos, etc. Ansible nos permite definir nuestros

364 © Alfaomega-RC Libros


CAPÍTULO 6: CARACTERÍSTICAS AVANZADAS

propios facts, para ello creamos un fichero con extensión .fact en formato INI
dentro del directorio /etc/ansible/facts.d/ del nodo administrado.

La variable que contendrá la información de los facts es ansible_local. A


continuación se muestra un ejemplo.

Fichero /etc/ansible/facs.d/datos.fact en el nodo


administrado.
[informacion]
departamento=it1
entorno=qa
soporte=12x5
Contenido del playbook.
- name: Obtener facts locales
hosts: www.oforte.net
gather_facts: True
tasks:
- debug: var=ansible_local
Resultado de la ejecución del playbook.
TASK [debug]
ok: [www.oforte.net] => {
"ansible_local": {
"datos": {
"informacion": {
"departamento": "it1",
"entorno": "qa",
"soporte": "12x5"
}
}
}
}

© Alfaomega-RC Libros 365


ANSIBLE GALAXY

INTRODUCCIÓN

Ansible Galaxy es un repositorio en línea, gratuito, donde se alojan roles que


pueden ser utilizados por nuestros Playbooks. Estos roles son creados por
personas individuales y no tienen soporte oficial por el equipo de desarrolladores
de Ansible, pero son de gran utilidad para desplegar una gran variedad de
aplicaciones y configurar sistemas.

La dirección web es http://galaxy.ansible.com y a través del link "Explore"


podemos ver los roles más descargados y populares.

En esta captura se observa que los roles más descargados son para
configurar/instalar redis, grafana, logrotate y composer. Al hacer clic sobre uno de
ellos se nos mostrará información detallada.
ANSIBLE

Además, se nos indican las plataformas soportadas y las versiones de este rol.

Para descargar un rol no es necesario poseer una cuenta en la plataforma. Es


posible compartir nuestros propios roles, para ello solo debemos tener una
cuenta y el código en GitHub. Desde el sistema donde tenemos Ansible instalado,
con el comando ansible-galaxy podremos:

368 © Alfaomega-RC Libros


CAPÍTULO 7: ANSIBLE GALAXY

● Descargar roles desde Galaxy o desde Gestión de Configuración de


Software (SCM).
● Crear roles.
● Eliminar roles.
● Realizar tareas en la web Galaxy:
○ Subir rol.
○ Editar rol.
○ Eliminar rol.

COMANDO ANSIBLE-GALAXY

El comando ansible-galaxy está disponible al instalar Ansible. La sintaxis es la


siguiente:

ansible-galaxy [acción] [opciones] argumentos

Las acciones disponibles son las siguientes:

● delete: elimina un rol de la web de Galaxy.


● import: importa un rol desde GitHub a Galaxy.
● info: muestra información detallada de un rol.
● init: inicializa una estructura de directorio.
● install: descarga un rol desde Galaxy: Por defecto dentro de
/etc/ansible/roles
● list: lista los roles instalados.
● login: autentifica en la web de Galaxy.
● remove: elimina un rol del servidor.
● search: hace una búsqueda dentro del repositorio.
● setup: crea una integración con Travis CI.

Las opciones disponibles son las siguientes:

● -f / --force: sobrescribe el rol indicado.


● -i / --ignore-errors: ignora errores.
● -n / --no-deps: no instala dependencias.
● -p / --roles-path: directorio para los roles.
● -r / --roles-file: fichero con lista de roles a instalar.

Ejemplos:

© Alfaomega-RC Libros 369


ANSIBLE

Buscar roles a través de la línea de comandos.


# ansible-galaxy search nginx
Found 421 roles matching your search:
Name Description
---- -----------
hxpro.nginx Nginx
donat-b.nginx NGiNX
tigr1991.nginx Nginx
SuperNami.nginx Nginx
bennojoy.nginx ansible role nginx
[..]
Mostrar información de un rol específico.
# ansible-galaxy info geerlingguy.nginx
Role: geerlingguy.nginx
description: Nginx installation for Linux, FreeBSD and OpenBSD.
active: True
[...] github_repo: ansible-role-nginx
github_user: geerlingguy
id: 471
is_valid: True
issue_tracker_url: https://github.com/geerlingguy/ansible-role-nginx/issues
license: license (BSD, MIT)
min_ansible_version: 1.8
[...]
## Role Variables
Available variables are listed below, along with default values (see
`defaults/main.yml`):
nginx_vhosts: []

Instalar rol desde Galaxy.


# ansible-galaxy install geerlingguy.nginx
- downloading role 'nginx', owned by geerlingguy
- downloading role from https://github.com/geerlingguy/ansible-role-
nginx/archive/2.5.0.tar.gz
- extracting geerlingguy.nginx to /etc/ansible/roles/geerlingguy.nginx
- geerlingguy.nginx (2.5.0) was installed successfully

Listar los roles instalados en el sistema.


# ansible-galaxy list
- geerlingguy.nginx, 2.5.0

Podemos utilizar el rol descargado, en el siguiente ejemplo se instala nginx


usando el rol descargado anteriormente.

370 © Alfaomega-RC Libros


CAPÍTULO 7: ANSIBLE GALAXY

Contenido del playbook.


- name: Instalar nginx
hosts: ansible01
remote_user: alberto
become: True
roles:
- geerlingguy.nginx
post_tasks:
- set_fact:
ip_servidor: "{{ ansible_host }}"
- uri:
url: "http://{{ ip_servidor }}"
register: respuesta
- debug: msg="Servidor web {{ respuesta.server }}"

Mensaje mostrado por debug.


TASK [debug] **********
ok: [ansible01] => {
"msg": "Servidor web nginx/1.10.3"
}

IMPORTAR NUESTRO ROL PARA GALAXY


Los pasos siguientes son:

● Crear un repositorio en GitHub.


● Inicializar el directorio rol con el comando ansible-galaxy o a mano.
● Editar el fichero README.md para describir la utilidad del rol.
● Editar el fichero meta/main.yml para especificar:
○ Autor del rol.
○ Descripción explicativa sobre el rol.
○ Plataformas soportadas.
○ Etiquetas.
○ Licencias.
○ Mínima versión de Ansible soportada.
● Publicar código (commit/push) a GitHub.
● Iniciar sesión con el comando ansible-galaxy login.
● Importar el rol usando el comando ansible-galaxy.

© Alfaomega-RC Libros 371


ANSIBLE

En la página de GitHub, es suficiente con crear un repositorio vacío para luego


ser utilizado para publicar nuestro código.

Con la acción init del comando ansible-galaxy inicializamos la estructura de un


directorio de un rol.

# ansible-galaxy init ejemplorol


- ejemplorol was created successfully
# tree ejemplorol/
ejemplorol/
├── defaults
│ └── main.yml
├── files
├── handlers
│ └── main.yml
├── meta
│ └── main.yml
├── README.md
├── tasks
│ └── main.yml
├── templates
├── tests
│ ├── inventory
│ └── test.yml
└── vars
└── main.yml

372 © Alfaomega-RC Libros


CAPÍTULO 7: ANSIBLE GALAXY

El contenido del ejemplo que se ha definido en README.md es el siguiente:

ejemplorol
=========
Este rol es un ejemplo para el libro Ansible
Requirements
------------
No hay prerrequisitos.
Role Variables
--------------
Las variables por defecto se definen en defaults/main.yml
Dependencies
------------
No dependencias
Example Playbook
----------------
Ejemplo:
- hosts: servers
roles:
- { role: agonzalezrh.ejemplorol }
License
-------
BSD
Author Information
------------------
Alberto Gonzalez <alberto@oforte.net>

El contenido del fichero meta/main.yml (sin comentarios) es el siguiente:

galaxy_info:
author: Alberto Gonzalez
description: Rol de ejemplo para el libro de Ansible
company: Oforte
license: BSD
min_ansible_version: 1.2
platforms:
- name: Debian
versions:
- all
- name: EL
versions:
- 7
galaxy_tags: ["libro", "ejemplo"]
dependencies: []

© Alfaomega-RC Libros 373


ANSIBLE

Este rol de ejemplo copia una plantilla (issue.j2) a /etc/issue y /etc/motd.

ejemplorol/defaults/main.yml
---
# defaults file for ejemplorol
destinos:
- /etc/issue
- /etc/motd

ejemplorol/tasks/main.yml
---
# tasks file for ejemplorol
- name: Generar fichero /etc/motd y /etc/issue
template:
src: issue.j2
dest: "{{ item }}"
with_items: "{{ destinos }}"
ejemplorol/templates/issue.j2
System Information For Hostname: {{ inventory_hostname }}
Distribution: {{ ansible_distribution }}
Distribution Release: {{ ansible_distribution_release }}
Distribution Version: {{ ansible_distribution_version }}
IP Address: {{ ansible_default_ipv4.address }}
DNS Server(s): {{ ansible_dns.nameservers|join (" ") }}
Kernel: {{ ansible_kernel }}
{% if ansible_lsb is defined %}
LSB: {{ ansible_lsb.description }}
{% endif %}
Memory Installed: {{ (ansible_memtotal_mb / 1024) | round(1) }}GB
Memory Swapfile: {{ (ansible_swaptotal_mb / 1024) | round(1) }}GB

Una vez publicado el código dentro del repositorio, será posible importarlo en
Galaxy.

# git init .
Initialized empty Git repository in /root/libro/ejemplorol/.git/
# git add .
# git commit -a -m "Primera version"
[master (root-commit) 0fed88a] Primera version
9 files changed, 92 insertions(+)
create mode 100644 README.md
create mode 100644 defaults/main.yml

374 © Alfaomega-RC Libros


CAPÍTULO 7: ANSIBLE GALAXY

create mode 100644 handlers/main.yml


create mode 100644 meta/main.yml
create mode 100644 tasks/main.yml
create mode 100644 templates/issue.j2
create mode 100644 tests/inventory
create mode 100644 tests/test.yml
create mode 100644 vars/main.yml
# git remote add origin https://github.com/agonzalezrh/ejemplorol.git
# git push -u origin master
Username for 'https://github.com': agonzalezrh
Password for 'https://agonzalezrh@github.com':
Counting objects: 18, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (9/9), done.
Writing objects: 100% (18/18), 1.86 KiB | 0 bytes/s, done.
Total 18 (delta 0), reused 0 (delta 0)
To https://github.com/agonzalezrh/ejemplorol.git
* [new branch] master -> master
Branch master set up to track remote branch master from origin.

El siguiente paso es autenticarnos utilizando ansible-galaxy login con nuestra


cuenta de GitHub.

# ansible-galaxy login
We need your Github login to identify you.
This information will not be sent to Galaxy, only to
api.github.com.
The password will not be displayed.
Use --github-token if you do not want to enter your password.
Github Username: agonzalezrh
Password for agonzalezrh:
Successfully logged into Galaxy as agonzalezrh

El último paso es importar el rol desde GitHub a Ansible Galaxy.

# ansible-galaxy import --role-name=ejemplorol agonzalezrh ejemplorol


Successfully submitted import request 218712
Starting import 218712: role_name=ejemplorol repo=agonzalezrh/ejemplorol
Accessing branch: master
Parsing and validating meta data.
Setting role name to ejemplorol
Parsing galaxy_tags
Parsing platforms

© Alfaomega-RC Libros 375


ANSIBLE

Parsing cloud platforms


No cloud platforms found in meta data
Parsing and validating README
Adding repo tags as role versions
Removing old tags
Import completed
Status SUCCESS : warnings=1 errors=0

Una vez finalizada la importación, podemos observar en la página de Ansible


Galaxy la información definida en meta/main.yml

Y en la pestaña de README podemos ver la información indicada en el fichero


README.md.

376 © Alfaomega-RC Libros


CAPÍTULO 7: ANSIBLE GALAXY

Ahora es posible instalarlo a través del comando ansible-galaxy.

# ansible-galaxy install agonzalezrh.ejemplorol


- downloading role 'ejemplorol', owned by agonzalezrh
- downloading role from
https://github.com/agonzalezrh/ejemplorol/archive/master.tar.gz
- extracting agonzalezrh.ejemplorol to
/etc/ansible/roles/agonzalezrh.ejemplorol
- agonzalezrh.ejemplorol (master) was installed successfully

FICHERO REQUISITOS
En nuestro proyecto de Ansible podemos tener un fichero (normalmente
llamado requirements.yml) que contiene los roles necesarios para nuestro
Playbook. Este fichero será utilizado para descargarlo desde Ansible Galaxy o
desde Gestión de Configuración de Software (SCM).

Ejemplo del contenido de un fichero:

© Alfaomega-RC Libros 377


ANSIBLE

# Descargar desde Galaxy


- src: agonzalezrh.ejemplorol
# Desde GitHb
- src: https://github.com/geerlingguy/ansible-role-nginx
version: master
name: nginx_role

Para instalar los roles definidos dentro del fichero, es necesario utilizar la
opción -r (--roles-file) con la acción install.

# ansible-galaxy -r requirements.yml install


- downloading role 'ejemplorol', owned by agonzalezrh
- downloading role from
https://github.com/agonzalezrh/ejemplorol/archive/master.tar.gz
- extracting agonzalezrh.ejemplorol to
/etc/ansible/roles/agonzalezrh.ejemplorol
- agonzalezrh.ejemplorol (master) was installed successfully
- extracting nginx_role to /etc/ansible/roles/nginx_role
- nginx_role was installed successfully# ansible-galaxy list
- agonzalezrh.ejemplorol, master
- nginx_role, (unknown version)

378 © Alfaomega-RC Libros


ANSIBLE TOWER

INTRODUCCIÓN

Ansible Tower es una solución web para facilitar las tareas de automatización a
todos los equipos dentro de IT. Los componentes son los siguientes:
● Proyectos: repositorio de Playbooks:
○ Alojados localmente
○ Gestión de Configuración de Software (SCM):
■ Git
■ Mercurial (hg)
■ Subversion
● Inventarios: estáticos o dinámicos (proveedores cloud, otros software de
inventario).
● Plantillas de trabajo: definición de playbook, inventario y diversas
opciones (como sudo, las credenciales a utilizar, etc..)
● Trabajos: se generan al ejecutar una plantilla.
● Configuración:
○ Credenciales.
○ Equipos (Teams).
○ Organizaciones
○ Permisos
○ Configuración de Tower:
■ Autenticación
■ Registros
■ Valores globales
ANSIBLE

Ansible Tower es un software de la compañía Red Hat y ofrece tres ediciones:

● self-support: sin soporte ni características especiales (autenticación LDAP,


workflows, alta disponibilidad, formularios, logging y análisis).
● standard: con soporte 8x5 pero sin características especiales.
● premium: soporte 24x7 y características especiales.

Es posible instalar la versión self-support de forma gratuita para administrar 10


nodos o menos. La web para solicitar esta versión o una versión trial durante un
mes es la siguiente: https://www.ansible.com/license

Existe un proyecto, de código abierto, que es el upstream de Ansible Tower


que se puede descargar de forma gratuita para administrar todos los nodos que se
requiera y las mismas funcionalidades, pero sin el soporte profesional de Red Hat.
La dirección web del proyecto es la siguiente: https://github.com/ansible/awx

INSTALACIÓN
Los requisitos para la instalación se detallan a continuación:

● Servidor(es) específicos para Ansible Tower, no compartir con otros


servicios.
● Distribuciones soportadas:
○ Red Hat Enterprise Linux 7.2 o posterior.
○ CentOS 7.2 o posterior.
○ Ubuntu 14.04 LTS / 16.04 LTS
● Navegador Google Chrome o Firefox, otros navegadores pueden funcionar
pero no soportados.
● Al menos 2 GB de RAM (recomendado más de 4 GB dependiendo de los
nodos administrados).
● Al menos 20 GB de disco, de los cuales 10 GB deben ser dedicados a /var.

Las diferentes arquitecturas posibles se indican a continuación:


● Todo en uno: un solo servidor que contiene la aplicación y la base de
datos.
● Base de datos externa: un servidor contiene la aplicación y otro la base de
datos (PostgreSQL versión 9.6).
● Alta disponibilidad (cluster): varios servidores con la aplicación y un nodo
separado para la base de datos (PostgreSQL versión 9.6).

380 © Alfaomega-RC Libros


CAPÍTULO 8: ANSIBLE TOWER

Hay dos formas de instalar Ansible Tower:

● Utilizando repositorios: donde se descarga solo un paquete necesario con


los playbooks para realizar la instalación y las dependencias necesarias se
descargan de los repositorios de la distribución. Para ello se utiliza el siguiente
enlace: http://releases.ansible.com/ansible-tower/setup/ansible-tower-setup-
latest.tar.gz
● Utilizando un bundle (solo para RHEL/CentOS): la mayoría de los paquetes
están incluidos en el fichero (tiene un mayor tamaño). La dirección es la
siguiente: https://releases.ansible.com/ansible-tower/setup-bundle/ansible-
tower-setup-bundle-latest.el7.tar.gz

Una vez descomprimido el fichero con el método de instalación que elijamos,


el fichero a editar se llama inventory donde definiremos la arquitectura a utilizar y
la contraseña del usuario administrador y la de los servicios. El ejemplo siguiente
muestra cómo instalar "todo en uno".

[tower]
localhost ansible_connection=local
[database]
[all:vars]
admin_password= 'l1br04ns1bl3''
pg_host=''
pg_port=''
pg_database='awx'
pg_username='awx'
pg_password='l1br04ns1bl3'
rabbitmq_port=5672
rabbitmq_vhost=tower
rabbitmq_username=tower
rabbitmq_password='l1br04ns1bl3'
rabbitmq_cookie=cookiemonster
rabbitmq_use_long_name=false

Una vez editado el fichero, para iniciar la instalación o realizar una


actualización de una versión a otra, solo es necesario ejecutar el script: setup.sh.
# ./setup.sh
[..]
PLAY RECAP **********
localhost : ok=116 changed=57 unreachable=0 failed=0
The setup process completed successfully.
Setup log saved to /var/log/tower/setup-2018-04-02-18:30:29.log

© Alfaomega-RC Libros 381


ANSIBLE

Después de instalar, al entrar en la dirección del servidor donde fue instalado,


accederemos con el usuario admin y la contraseña indicada en el fichero de
inventario.

Una vez identificados, nos pedirá el fichero de licencia necesario para poder
utilizar el producto.

Una vez especificado el fichero de licencia y aceptado las condiciones, nos


aparecerá la página principal de Ansible Tower.

382 © Alfaomega-RC Libros


CAPÍTULO 8: ANSIBLE TOWER

CONFIGURACIÓN
Una vez instalado Ansible Tower es posible configurar los siguientes
elementos:

● Organizaciones: agrupar contenido para administrar permisos de los


diferentes departamentos.
● Usuarios: permitir a usuarios el uso de Tower.
● Equipos: dividir una organización para asociar contenido y controlar
permisos.
● Credenciales: añadir contraseñas, claves SSH, claves de cloud… Para
acceder a servidores, inventarios o a repositorios.
● Trabajos de gestión: gestionar trabajos administrativos como limpiar
historial, flujos de actividad, etc.
● Scripts de inventario: en el caso de no tener integración nativa a su
inventario, es posible definir un script personalizado para obtener la lista de
nodos a administrar.
● Notificaciones: crear plantillas para notificar el resultado de un trabajo.
Utilizando email, Hipchat, Slack o SMS.

© Alfaomega-RC Libros 383


ANSIBLE

● Licencia: ver o modificar la licencia actual.


● Grupo de instancias: en el caso de alta disponibilidad, es posible agrupar
servidores con afinidad y poder ser utilizados para ejecutar trabajos.
● Configurar Tower: diferentes opciones internas de la aplicación, desde la
autenticación hasta el logo.

ORGANIZACIÓN

Una organización es una colección de usuarios, equipos e inventarios. Es el


nivel más alto de una jerarquía, como se muestra en el siguiente diagrama:

Pulsando sobre Ajustes-> Organizaciones se muestran las organizaciones


existentes y el número de los diferentes elementos dentro de ellas. Por defecto
existe una organización llamada Default.

Al crear un nueva organización (solo posible en licencia Premium) se solicitarán


el nombre y la descripción de la misma.

USUARIOS

Un usuario es alguien que tiene permiso para acceder a Tower con las
credenciales y los permisos correctos. Existen tres tipos de usuarios:

384 © Alfaomega-RC Libros


CAPÍTULO 8: ANSIBLE TOWER

● Usuario normal: tienen acceso de lectura y/o escritura limitado a ciertos


recursos (inventarios, proyectos y plantillas de trabajo) a los que se le han
asignado permisos.
● Auditor de sistema: tiene acceso de lectura solo para todos los elementos
dentro del entorno de de Tower.
● Administrador de sistema: tiene permiso de administrador, lectura y
escritura sobre todo la instalación de Tower.

El usuario por defecto, con el que nos hemos autenticado y hemos definido la
contraseña en el fichero de inventario, es admin.

Al crear un usuario definiremos los siguientes datos: nombre, apellidos,


organización a la que pertenece dentro de Tower, correo electrónico, el nombre
de usuario, la contraseña y el tipo de usuario (normal, auditor, administrador).

© Alfaomega-RC Libros 385


ANSIBLE

EQUIPOS

Un equipo es una subdivisión de una organización con usuarios, proyectos,


credenciales y permisos asociados. Un equipo permite implementar un RBAC
(control de acceso basado en roles) y delegar responsabilidades a través de
organizaciones.

Al crear un equipo, se indican los siguientes datos: nombre, descripción


(opcional) y organización.

Una vez creado el equipo, podemos asociar usuarios al mismo e indicar el rol
dentro del equipo: administrador o miembro.

386 © Alfaomega-RC Libros


CAPÍTULO 8: ANSIBLE TOWER

CREDENCIALES

Las credenciales son utilizadas por Tower para autenticar al lanzar trabajos
sobre máquinas, sincronizar inventarios e importar proyectos desde un sistema de
control de versiones.

Es posible dar permiso a los usuarios para poder utilizar estas credenciales, sin
necesidad de que dicho usuario tenga acceso real a la información. Al crear una
credencial se especifica la siguiente información: nombre, descripción (opcional),
organización y el tipo de credencial de la siguiente lista:

● Proveedores, para acceder al inventario:


○ Amazon Web Services
○ Google Compute Engine
○ Microsoft Azure Resource Manager
○ OpenStack
○ Red Hat CloudForms
○ Red Hat Satellite 6
○ Red Hat Virtualization
○ VMware vCenter
● Insights
● Machine (servidor), usando:
○ Clave SSH.
○ Usuario/contraseña.
○ Si utilizar escalación (sudo, su, runas, etc.) y el usuario para ello.
● Network (dispositivo de red), usando:
○ Clave SSH.
○ Usuario/contraseña.
● Source Control (gestor de control de versiones), usando:
○ Clave SSH.
○ Usuario/contraseña.
● Vault (Almacenar contraseñas de forma segura).

© Alfaomega-RC Libros 387


ANSIBLE

TRABAJOS DE GESTIÓN

Ansible Tower viene con tres trabajos de gestión para limpiar información
antigua.

SCRIPTS DE INVENTARIO

Es posible añadir un script personalizado para obtener la lista de nodos a


administrar desde un origen diferente a los que incluye Tower.

388 © Alfaomega-RC Libros


CAPÍTULO 8: ANSIBLE TOWER

NOTIFICACIONES

Una notificación es utilizada para comunicar a una lista de destinatarios


cuándo una tarea termina, ya sea de forma satisfactoria o fallida. Al crear una
plantilla de notificación se especifica: nombre, descripción (opcional),
organización y el tipo de notificación (Correo, Slack, Twilio, Pagerduty, HipChat,
Webhook o IRC).

© Alfaomega-RC Libros 389


ANSIBLE

LICENCIA

Dentro de esta sección es posible ver la información de la licencia actual o


subir una nueva licencia.

GRUPO DE INSTANCIAS

Por defecto se crea un grupo llamado tower.

En el caso de utilizar alta disponibilidad, en el inventario de instalación se


pueden definir nuevos grupos (un servidor al menos debe estar en tower), un
ejemplo:

[tower]
servidorglobal
[instance_group_europa]
servidorsp
servidorde

390 © Alfaomega-RC Libros


CAPÍTULO 8: ANSIBLE TOWER

[instance_group_americana]
servidormx
servidorco

CONFIGURAR TOWER

En esta sección se pueden configurar diferentes parámetros de la aplicación.

Autentificación

Por defecto, la autenticación está basada en la base de datos propia de Tower.


Es posible definir una autentificación externa para que los usuarios se puedan
autenticar con el usuario/contraseña desde un proveedor externo. Las opciones
son las siguientes:

● Azure AD
● GitHub
● GitHub Org
● GitHub Team
● Google OAuth2
● LDAP
● RADIUS
● SAML
● TACACS+

© Alfaomega-RC Libros 391


ANSIBLE

Trabajos

Es posible configurar ciertos parámetros sobre los trabajos, como el número


máximo de trabajos programados, en qué directorio se alojarán los ficheros
temporalmente y distintas configuraciones de seguridad.

Sistema

En este apartado se pueden configurar diferentes opciones de la aplicación.

Miscelánea

En esta categoría se puede configurar la dirección url del sistema, el tiempo de


inactividad o el número de sesiones simultáneas entre otras opciones.

392 © Alfaomega-RC Libros


CAPÍTULO 8: ANSIBLE TOWER

Registros

En esta categoría es posible configurar el envío de los registros a un sistema


externo.

© Alfaomega-RC Libros 393


ANSIBLE

Flujo de actividad

En esta categoría es posible indicar si se quiere registrar toda la actividad que


sucede dentro de la aplicación.

Interfaz de usuario

En este apartado se puede cambiar el logo, añadir una descripción a la página


inicial de autenticación o deshabilitar el seguimiento analítico de Google.

Proyectos
Un proyecto hace referencia a dónde están alojados los playbooks y todos los
ficheros necesarios (plantillas, roles, etc.). Pueden estar alojados en:

● SCM (Control de versiones): Git, Subversion o Mercurial.


● Local: alojado como subdirectorio en el directorio /var/lib/awx/projects/,
debe tener como dueño al usuario awx.

En caso de necesitar autenticarse para acceder al SCM, dentro del tipo de


autenticación es posible utilizar clave SSH o usando usuario/contraseña. Al añadir
un nuevo proyecto se mostrará el siguiente formulario.

394 © Alfaomega-RC Libros


CAPÍTULO 8: ANSIBLE TOWER

Las opciones disponibles al utilizar SCM son las siguientes:

● Limpiar: elimina el contenido del directorio antes de sincronizar


de nuevo.
● Eliminar la actualización: si el directorio donde se ha descargado
el repositorio ha sido modificado, esta opción eliminará esos cambios.
● Actualizar al ejecutar: indica que al ejecutar un trabajo, de forma
automática se obtendrá la última versión desde el repositorio.

Inventarios

Un inventario contiene una lista de nodos a administrar (con sus atributos). Un


nodo en varios inventarios cuenta solo como uno en relación con los nodos
licenciados. El inventario puede ser manual, creando los nodos y los grupos desde
la interfaz web, o de forma dinámica a través de proveedores soportados o
usando un script personalizado. Los proveedores para inventario dinámico son los
siguientes:

● Amazon EC2
● Google Compute Engine
● Microsoft Azure Resource Manager
● VMware vCenter

© Alfaomega-RC Libros 395


ANSIBLE

● Red Hat Satellite 6


● Red Hat Cloudforms
● OpenStack
● Red Hat Virtualization
● Ansible Tower

Además, también es posible utilizar un fichero de inventario que está dentro


de un proyecto de Tower.

Al añadir un inventario hay que especificar un nombre, descripción (opcional),


organización y grupo de instancias (opcional). Además, es posible especificar
variables globales para todos los servidores dentro de dicho inventario.

Una vez guardado, podemos añadir los grupos y servidores manualmente o


utilizar las fuentes como inventarios dinámicos.

396 © Alfaomega-RC Libros


CAPÍTULO 8: ANSIBLE TOWER

FUENTES

Una vez sincronizada la fuente, se llenarán los servidores y los grupos con la
información obtenida desde el proveedor.

© Alfaomega-RC Libros 397


ANSIBLE

Si entramos en los detalles de un servidor, se mostrarán las variables


autogeneradas por el inventario dinámico.

AD HOC

Es posible ejecutar tareas rápidas en uno o varios servidores a través de


ad hoc. Para ello seleccionamos un servidor o varios, o un grupo, y pulsamos
Ejecutar comandos. A continuación especificamos el módulo a utilizar (de la lista
de módulos habilitados por el administrador en la configuración) y los argumentos
necesarios, además de la credencial para conectarnos a los nodos.

398 © Alfaomega-RC Libros


CAPÍTULO 8: ANSIBLE TOWER

Credenciales

Como hemos visto en la sección de configuración, hay diferentes tipos de


credenciales. Para conectarnos a los sistemas utilizaremos la credencial de
Machine.

© Alfaomega-RC Libros 399


ANSIBLE

Plantillas

Una plantilla contiene la definición de todos los elementos para ejecutar un


playbook en los nodos deseados del inventario especificado. Se definen los
siguientes elementos:

● Nombre: nombre de la plantilla.


● Descripción: descripción de la plantilla (opcional).
● Tipo de trabajo: dos opciones.
○ Ejecutar: realiza las acciones en el servidor.
○ Comprobar: no realiza las acciones en el servidor, solo se conecta
y simula ejecutarlo.
● Inventario: el inventario a utilizar.
● Proyecto: el proyecto que contiene los playbooks a ejecutar.
● Playbook: el playbook dentro del proyecto a ejecutar en los nodos
administrados.
● Credencial: la credencial a utilizar para conectarse al servidor y otras que
puedan ser necesarias (vault o cloud para ciertos módulos).
● Forks: define cuántos trabajos en paralelo se permiten.
● Límite: patrón indicando los servidores a utilizar dentro del inventario, si
está vacío se utilizarán todos.
● Nivel de detalle: normal, verbose, more verbose, debug, debug de
conexión o WinRM debug.
● Grupo de instancias: qué servidores dentro de la alta disponibilidad
utilizaremos para iniciar el trabajo.
● Etiquetas de trabajo: las etiquetas (tags) a utilizar cuando llamamos al
playbook.
● Omitir etiquetas: las etiquetas (tags) a omitir cuando llamamos al
playbook.
● Etiquetas: etiquetas a utilizar dentro de la aplicación de Tower.
● Variables adicionales: variables extra que se pasarán al playbook.
● Otras opciones:
○ Mostrar cambios: mostrará los cambios realizados cuando se
utilicen módulos de tratado de ficheros.
○ Activar la elevación de permisos: indica si se utilizará un usuario
administrador.
○ Activar los trabajos concurrentes: indica si esta plantilla puede
ejecutarse como un trabajo en paralelo o debe ejecutarse en
secuencia.

400 © Alfaomega-RC Libros


CAPÍTULO 8: ANSIBLE TOWER

○ Usar caché de eventos: si se deben almacenar los eventos en el


caché.
○ Permitir la ejecución utilizando Callbacks: genera una dirección
url que puede ser llamada desde un nodo administrado para inicializar
un trabajo usando esta plantilla, pero limitándose solo al servidor que
lo llama.

Además en muchos elementos se puede activar Preguntar al ejecutar para que


aparezca un formulario al ejecutar esta plantilla pidiendo los datos indicados.

Plantillas de flujo de trabajo


Con la licencia premium es posible crear un workflow (flujo de trabajo) para
llamar a distintas plantillas dentro de un flujo dependiendo de diferentes
condiciones.

© Alfaomega-RC Libros 401


ANSIBLE

Al crear una plantilla de flujo de trabajo especificaremos el nombre y


opcionalmente: descripción, organización, etiquetas en la aplicación y variables
adicionales que se pasarán a las plantillas.

Una vez guardada la plantilla de flujo de trabajo es posible presionar sobre


"Editor de flujo de trabajo" para diseñar nuestro workflow.

402 © Alfaomega-RC Libros


CAPÍTULO 8: ANSIBLE TOWER

Como se ve en el ejemplo anterior, es posible definir un flujo dependiendo si


un trabajo ha fallado (rojo), ha sido correcto (verde) o siempre (azul).

Trabajos
Un trabajo contiene la información sobre una plantilla ejecutada u otro trabajo
interno:

● Sincronizar un repositorio.
● Sincronizar un inventario.
● Trabajos internos:
○ Limpiar logs.
○ Otras tareas varias.
● Trabajos programados -> Plantillas ejecutadas periódicamente.

Cuando sincronizamos un proyecto se genera un trabajo de tipo "Actualización


SCM".

© Alfaomega-RC Libros 403


ANSIBLE

Al sincronizar un inventario desde un proveedor o desde un fichero de un


proyecto se generará un trabajo de tipo "Sincronizar inventario".

Al ejecutar una plantilla ( ) se generará un trabajo de tipo


"Ejecutar Playbook".

404 © Alfaomega-RC Libros


CAPÍTULO 8: ANSIBLE TOWER

Programar

Es posible programar plantillas ( ) para que se ejecuten de


forma periódica.

Existe una lista de trabajos programados, que se especifican en


Plantillas->Programaciones.

© Alfaomega-RC Libros 405


ANSIBLE

Notificaciones
Es posible configurar notificaciones para que el trabajo generado cuando se
ejecuta la plantilla notifique al finalizar si ha sido correctamente o ha fallado.

Un ejemplo de un correo recibido cuando una tarea ha finalizado


correctamente se muestra a continuación.

406 © Alfaomega-RC Libros


CAPÍTULO 8: ANSIBLE TOWER

Permisos
Es posible asignar de forma granular permisos dentro de Ansible Tower a los
componentes.

PROYECTOS

A los usuarios y a los equipos se le puede asignar los siguientes roles:

● Admin: el usuario o los miembros del equipo podrán editar el proyecto.


● Uso: el usuario o los miembros del equipo podrán usar pero no editar el
proyecto.
● Actualización: el usuario o los miembros del equipo, en caso de ser
proyecto SCM podrán actualizar el repositorio.

INVENTARIOS

A los usuarios y a los equipos se le puede asignar los siguientes roles:

● Admin: el usuario o los miembros del equipo podrán editar el inventario.

© Alfaomega-RC Libros 407


ANSIBLE

● Uso: el usuario o los miembros del equipo podrán usar pero no editar el
inventario.
● Actualización: el usuario o los miembros del equipo, en caso de ser
inventario dinámico podrán actualizar el inventario.
● Ad Hoc: el usuario o los miembros del equipo podrán ejecutar acciones en
los nodos (usando los módulos) sin necesidad de una plantilla.

PLANTILLAS

A los usuarios y a los equipos se le puede asignar los siguientes roles:

● Admin: el usuario o los miembros del equipo podrán editar la plantilla.


● Ejecutar: el usuario o los miembros del equipo podrán ejecutar la plantilla
pero no editarla.

408 © Alfaomega-RC Libros


CAPÍTULO 8: ANSIBLE TOWER

CREDENCIALES

A los usuarios y a los equipos se le puede asignar los siguientes roles:

● Admin: el usuario o los miembros del equipo podrán editar la credencial.


● Uso: el usuario o los miembros del equipo podrán ejecutar la credencial
pero no editarla.

© Alfaomega-RC Libros 409


ANSIBLE

Avanzado
Algunas de las características avanzadas en Tower son:

INVENTARIO INTELIGENTE

Permite crear un inventario basado en la búsqueda de ciertos facts o variables.


Los nodos pueden ser filtrados desde varios inventarios.

410 © Alfaomega-RC Libros


CAPÍTULO 8: ANSIBLE TOWER

ENCUESTA (SURVEY)

Permite crear un formulario que será solicitado al ejecutar una plantilla. En


este formulario se definirán variables que serán pasadas al playbook, en vez de
tener que escribirlas en YAML/JSON. Con la licencia premium, presionando sobre
"Encuesta" (Survey) se abre el diseñador de formulario.

Los tipos de respuestas disponibles son:

● Texto.
● Área de texto.
● Contraseña.
● Lista (seleccionar opción única).
● Lista (seleccionar múltiples opciones).
● Número (entero).
● Número (decimal).

Por ejemplo si se define la siguiente encuesta (survey) con cuatro preguntas:

© Alfaomega-RC Libros 411


ANSIBLE

Al ejecutar la plantilla se mostrará de esta manera.

412 © Alfaomega-RC Libros


CAPÍTULO 8: ANSIBLE TOWER

CALLBACK

Es posible configurar una plantilla para ser llamada desde el nodo


administrado a través de una url.

Desde un nodo que esté definido dentro del inventario de esa plantilla,
podemos hacer una llamada a la web indicada y la clave indicada para iniciar ese
trabajo en el nodo. Por ejemplo:

© Alfaomega-RC Libros 413


ANSIBLE

ansible01:~$ curl --data "host_config_key=6407c588746ca5617362ab19d5ef70e7"


https://tower.oforte.net/api/v2/job_templates/9/callback/
ansible01:~$

En la lista de trabajos podemos ver que un nuevo trabajo aparece para esa
plantilla con la siguiente información.

COPIA DE SEGURIDAD / RESTAURACIÓN

Es posible realizar copias de seguridad y restaurarlas usando el mismo script


que utilizamos para la instalación: setup.sh.

Para hacer una copia de seguridad añadiremos la opción -b a la llamada al


script.

ansible-tower-setup-bundle-3.2.3-1.el7# ./setup.sh –b
[..]
RUNNING HANDLER [backup : Remove the common tarball.] *******************
changed: [localhost] => {"changed": true, "path":
"/var/backups/tower/common.tar.gz", "state": "absent"}
RUNNING HANDLER [backup : Remove backup dest stage directory.] *********
changed: [localhost] => {"changed": true, "path": "/root/ansible-tower-
setup-bundle-3.2.3-1.el7/2018-04-07-17:28:56", "state": "absent"}
PLAY RECAP **********
localhost : ok=31 changed=23 unreachable=0 failed=0
The setup process completed successfully.
Setup log saved to /var/log/tower/setup-2018-04-07-17:28:51.log

414 © Alfaomega-RC Libros


CAPÍTULO 8: ANSIBLE TOWER

Dentro del directorio actual, se creará el backup y un enlace a la última versión


de la copia de seguridad (útil al ejecutar la copia de seguridad de forma
programada).

# ls -ltr tower-backup-*
-rw-r--r--. 1 root root 619895 Apr 7 17:29 tower-backup-2018-04-07-17:28:56.tar.gz
lrwxrwxrwx. 1 root root 84 Apr 7 17:29 tower-backup-latest.tar.gz -> /root/ansible-
tower-setup-bundle-3.2.3-1.el7/tower-backup-2018-04-07-17:28:56.tar.gz

La restauración se realiza utilizando la opción -r y utilizará el fichero tower-


backup-latest.tar.gz

ansible-tower-setup-bundle-3.2.3-1.el7# ./setup.sh –r
TASK [Start Tower services on all nodes] **
changed: [localhost] => {"changed": true, "cmd": ["ansible-tower-
service", "start"], "delta": "0:00:03.661157", "end": "2018-04-07
17:33:07.284704", "rc": 0, "start": "2018-04-07 17:33:03.623547",
"stderr": "Redirecting to /bin/systemctl start postgresql-
9.6.service\nRedirecting to /bin/systemctl start rabbitmq-
server.service\nRedirecting to /bin/systemctl start
nginx.service\nRedirecting to /bin/systemctl start
supervisord.service", "stderr_lines": ["Redirecting to
/bin/systemctl start postgresql-9.6.service", "Redirecting to
/bin/systemctl start rabbitmq-server.service", "Redirecting to
/bin/systemctl start nginx.service", "Redirecting to
/bin/systemctl start supervisord.service"], "stdout": "Starting
Tower", "stdout_lines": ["Starting Tower"]}
PLAY [database] *******
skipping: no hosts matched
PLAY RECAP **********
localhost : ok=38 changed=20 unreachable=0 failed=0
The setup process completed successfully.
Setup log saved to /var/log/tower/setup-2018-04-07-17:32:40.log

© Alfaomega-RC Libros 415


ÍNDICE ANALÍTICO

A C
ad-hoc ........................................................ 26 changed ...................................................... 10
always ........................................................ 70 changed_when........................................... 68
ansible.cfg............................................... 8 check_mode ............................................... 40
ansible_become ..................................... 13 children .................................................... 14
ansible_become_method ..................... 13 código fuente .......................................... 7
ansible_become_user.......................... 13 comentario ............................................... 54
ansible_connection .......................... 111 condición.................................................. 55
ansible_host .......................................... 13 condiciones ............................................. 39
ansible_port .......................................... 13 control_path........................................... 34
ansible_ssh_pass ................................. 13 control_path_dir ................................. 34
ansible_user .......................................... 13 csvfile .................................................... 318
ansible-galaxy ................................... 368 cyberark .................................................. 292
ansible-playbook ................................. 33
ansible-vault ...................................... 348 D
any_errors_fatal ............................... 355
async ................................................. 131, 352 defaults .................................................... 32
azure ......................................................... 253 delegate_facts .................................... 355
delegate_to ............................................ 64
docker ................................................. 13, 263
B
become ................................................ 34, 308 E
--become.................................................... 12
become_ask_pass ................................... 34 env .............................................................. 129
become_method .................................. 34, 40 etiquetas................................................ 315
become_user............................................ 34, --extra-vars........................................... 41
259, 260
bloques ...............................69, 169, 170, 259 F
bucles .......................................... 42, 54, 361
failed ......................................................... 30
failed_when ............................................ 68
ANSIBLE

file ......................................................... 8, 27 módulo debug........................................... 42


files ........................................................... 50 módulo fetch........................................... 86
filtros .................................................... 173 módulo group........................................... 75
force_handlers ................................... 355 módulo lineinfile............................... 94
forks ........................................................... 33 módulo lvg ............................................. 187
módulo package .................................... 115
G módulo setup........................................... 31
módulo stat ............................................. 98
gentoo ...................................................... 116 módulo template ................................. 223
google ................................................ 91, 268 módulo user ................................... 180, 238
módulo wait_for ................................. 141
H módulo win_chocolatey ................... 210
módulo win_package .......................... 115
handlers.................................................... 43
módulo yum ............................................... 26
host_key_checking .............................. 33
módulo zypper ...................................... 124
módulo zypper_repository ............ 124
I módulos ........................................................ 2
ignore_errors ........................................ 65
import_playbook ................................... 46 N
import_role............................................. 51
no_log ....................................................... 355
include ...................................................... 45
notify ......................................................... 43
include_role .......................................... 49
include_tasks ........................................ 46
include_vars .......................................... 46 O
ini................................................................ 22 opciones avanzadas .......................... 355
instalación............................................... 5 openssl_certificate ........................ 301
inventario dinámico.......................... 21 openssl_csr ........................................... 301
--inventory............................................. 12 openssl_privatekey .......................... 301
inventory_ignore_extensions....... 25 openssl_publickey............................. 301
ipa.............................................................. 292 openstack................................................ 132
item ............................................................. 58

P
L
password .................................................... 10
libvirt ............................................ 274, 275
permisos .................................................... 13
listen .................................................. 44, 45
pip .................................................................. 5
--lists-tasks ........................................ 41 pipe ................................................... 319, 361
pipelining ............................................... 34
M plantillas ................................. 3, 383, 401
play ............................................................. 37
max_fail_percentage........................ 355 playbook .................................................... 37
meta50, 51, 53, 131, 132, 371, 372, 373, 374, 375, 376 poll ........................................................... 140
módulo command ..................................... 26 post_tasks ............................................... 51
módulo copy............................... 26, 38, 323 pre_tasks.................................................. 51
módulo cpanm ........................................ 105 pywinrm ...................................................... 35

418 © Alfaomega-RC Libros


ÍNDICE ANALÍTICO

R U
register.................................................... 49 ungrouped.................................................. 16
remote_port............................................. 33 url .............................................................. 111
remote_user............................................. 33
requirements.yml ............................... 377 V
rescue ........................................................ 70
roles ........................................................... 41 -v, --verbose ........................................ 41
run_once.................................................. 355 variables................................................. 13
variables globales .................. 156, 396
vars ............................................................. 14
S
vars_files ............................................... 46
scp_if_ssh ............................................... 34 vault ......................................................... 319
selinux ...................................................... 32
serial ...................................................... 355 W
skipped ...................................................... 39
solaris .................................................... 171 when ............................................................. 55
ssh_args.................................................... 34 windows ...................................................... 13
--start-at-task ................................... 41 winrm ............................................. 35, 36, 208
stderr ........................................................ 29 with_dict.................................................. 61
stderr_lines .......................................... 63 with_file................................................ 361
stdout ........................................................ 29 with_fileglob ...................................... 361
stdout_lines .......................................... 29 with_filetree ...................................... 362
--step ........................................................ 41 with_items .............................................. 58
--syntax-check ..................................... 41 with_nested ............................................ 60
with_random_choice .......................... 362
with_sequence ...................................... 362
T
with_together ...................................... 362
tags ........................................................... 246
tasks ........................................................... 37 Y
template.................................................... 51
templates ................................................. 50 yaml ............................................................. 39
timeout ...................................................... 33
Z
zabbix ....................................................... 287

© Alfaomega-RC Libros Descargado en: eybooks.com 419

También podría gustarte