Puppet y relaciones de dependencia entre recursos
Puppet declara dependencias de manera implícita, pero no siempre se cargan los recursos de la manera esperada. En Puppet hay tres maneras de declaraciones implícitas
- title hash: Es una ordenación aleatoria pero consistente
- manifest: Ordena siguiendo el orden de declaración en el manifiesto (por defecto en Puppet 4)
- random: Aleatorio en cada ejecución. Es útil para debuggar problemas con relaciones de dependencia
Los metaparámetros de dependencia explicita proveen un medio de organización de dependencias muy potente. Veámoslo.
Ordenando recursos
En la siguiente declaración se declara una dependencia:
package { 'nginx': ensure => 'present', before => Service['nginx'] } service { 'nginx': ensure => 'running', enabled => 'true', require => Package['nginx'] }
En este caso, el servicio ‘nginx’ se ejecutará sólo si el packete ‘nginx’ está presente. Los metaparámetros before y require son reduntanes en este caso y no ofrecen datos a otros recursos. En la declaraciones explicitas no es necesario declarar relaciones innecesarias, ya que hace más frágil el manifiesto.
Disparadores de eventos
Los metaparámetros notify y subscribe funcionan de manera similar a los dos anteriores, pero también enviarán eventos de refresco (refresh events) al recurso dependiente si la dependencia cambia. Por ejemplo, un servicio dependiente se recargará si su configuración cambia.
package { 'nginx': ensure => 'latest', notify => Service['nginx'] } service { 'nginx': ensure => 'running', enabled => 'true', subscribe => Package['nginx'] }
Cuando el paquete nginx se actualice a la última versión, el recurso enviará un refresh event al servicio nginx para que se recargue. Ambos metaparámetros son redundantes.
El evento de refresco tiene un significado especial para recursos exec con el atributo refreshonly. Estos recursos sólo se aplicarán sí, y sólo si, la dependencia cambia.
file {'nombre': ensure => 'file', source => 'puppet://puppetserver/modules/module_name/name.sh', path => '/usr/local/bin/name.sh', notify => Exec['name.sh'] } exec {'name.sh'': path => '/usr/local/bin', logoutput => 'true' refreshonly => true, }
En script name.sh no se ejecutará a menos que el archivo se haya creado.
Flechas para encadenar recursos
La relaciones dependencia anteriores pueden declararse usando flechas aunque, sin embargo, su uso está desaconsejado por ser de lectura más difícil. Por ejemplo, para instalar Nginx antes que iniciar el servicio:
Package ['nginx'] -> Service['nginx']
Para envíar un evento de refresco:
Package ['nginx'] ~> Service['nginx']
Es posible expresarlo a la inversa, pero esto no habría que hacerlo nunca:
Service['nginx'] <~ Package ['nginx']
Colectores
Un colector es un grupo de varios recursos. Hay que usarlo con precaución, ya que puede tener consecuencias inintencionadas nefastas. Se declara con el tipo de recurso seguido de <| atributo |> Por ejemplo:
User <||> # Todos los usuarios declarados Service <| ensure == running |> # Todos los servicios que están ejecutándose Package <| tag == 'http' |> # Todos los paquetes etiquetado con 'http'
La condición de búsqueda puede ser booleana:
Service <| (ensure == running) or (enabled == true ) |> Service <| (ensure == running) and (title != system' ) |>
En resumen
Hemos visto los siguientes controles:
- before y la flecha -> Expresa una dependencia
- notify y la flecha ~> Envía un refresh event
- require Exprea un recurso dependiente
- subscribe Se aplica cuando recibe un refresh event
- refreshonly Se ejectuta sólo cuando recibe un refresh event