Archivo del Autor: Gustavo Moreno

dos mujeres interactuando con sus moviles

Cómo migrar una app de Google Play a Amazon App Store

Para migrar en Amazon App Store una app que ya ha sido instalada en en Google, es suficiente con muy pocos cambios.

Preparacion de la APP


Version Name: en tu AndroidManifest.xml usa el atributo android:versionName para definir el nombre que será mostrado a los usurios.
Version Number: android:versionCode Igual que en Google Play
Device filtering: En tu AndroidManifest.xml especificar los dispositivos en los que se vara la apliciacion. Este atributo es obligatorio en Amazon

Por ejemplo:

<supports-screens
android:smallScreens="false"
android:normalScreens="true"
android:largeScreens="true"
android:xlargeScreens="false"
android:requiresSmallestWidthDp="335"/>

y recomendable en Google Play. Lo suyo es dejarlo tambien en Google, con lo que en archivo APK prácticamente solo hay que hacer un cambio: el archivo APK debe compilarse sin claves para firmar.

El proceso de subir el archivo se hace en la consola de desarrolladores. Es muy intuitivo y parecido al de Google Play. El título de la app que se rellena en la ficha solo será para uso de la consola, pero es necesario que no sea demasiado común para no confundirlo con otras apps, según me dijeron en Amazon al rechazarme una app durante un test previo a la publicación.

En resumen:

  1. Diferencias en librerías

    Prácticamente funcionan todas la librerías, con algunas salvedades relacionadas con los recursos computacionales de Amazon

    //developer.amazon.com/es/docs/app-submission/migrate-existing-app.html#APIsandServices

  2. Device Filtering

    <supports-screens
    android:smallScreens=»false»
    android:normalScreens=»true»
    android:largeScreens=»true»
    android:xlargeScreens=»false»
    android:requiresSmallestWidthDp=»335″/>

  3. Subir APK a Amazon App Store

    Puede ser suficiente el mismo código fuente de Google Play, compilado sin firmar.

Más documentación: //developer.amazon.com/es/docs/app-submission/getting-started.html

vagrant con puppet server

Vagrant y Puppet Server para pruebas de entornos

El objetivo es tener en Vagrant un servidor Puppet y al menos dos servidores agentes. En este post no trataré la creación de manifiestos, sino que llegará hasta la firma automática de certificados SSL de cuantos agentes se deseen.

Estos son entornos son muy útiles para reproducir en una máquina local, o servidor dedicado, un entorno de producción para poner a prueba la configuración de los servicios y aplicaciones.

Empezando con Vagrant

Todo los scripts los he usado con la versión de Vagrant de los repositorios de Ubuntu 18.04 y Virtualbox como aprovisionador también de los repositorios.

Puppet Server

Vagrant.configure("2") do |config|
  config.vm.box = "generic/debian9"
  config.vm.hostname = "obelix"
  config.vm.network "public_network",ip: "192.168.1.90",bridge: "enp12s0"
  config.vm.provider "virtualbox"# do |vb|
     vb.gui = false
     vb.memory = "2048"
  end
  config.ssh.insert_key = false
  config.ssh.private_key_path = ["~/.vagrant.d/insecure_private_key","/home/gustavo/.ssh/gmoreno", ]
  config.vm.provision "file", source: "~/.ssh/gmoreno.pub", destination: "~/.ssh/authorized_keys"
  config.vm.provision "file", source: "puppet.conf", destination: "/home/vagrant/puppet.conf"
  config.vm.provision "shell", path: server.sh
end

config.vm.box: la caja o «imagen» que usará para el aprovisionador. En este caso una imagén generica de Debian Stretch

config.vm.hostname: el hostname que tendrá la VM.

config.vm.network: confgiura una red publica, con una dirección IP estática y el bridge de la misma interfaz del sistema anfitrión.

config.vm.provider: Define Virtualbox como aprovisonador, sin entorno gráfico y con 2048 Mb de memoría RAM.

En el siguiente segmento se aprovisona una llave para hacer una conexión por SSH:

 config.ssh.insert_key = false
 config.ssh.private_key_path = ["~/.vagrant.d/insecure_private_key","/home/usuario/.ssh/id_rsa", ]
 config.vm.provision "file", source: "~/.ssh/id_rsa.pub", destination: "~/.ssh/authorized_keys"

Con estos envíamos a la VM una llave privada SSH (llamada en este caso id_rsa). También una llave pública que se añade al authorized_keys. De este modo, se prepara el logueo por SSH. Harán falta algunas instrucciones más.

 config.vm.provision "file", source: "puppet.conf", destination: "/home/vagrant/puppet.conf"
 config.vm.provision "shell", path: server.sh

Se copia el archivo puppet.conf desde el anfitrión a la VM y el script bootstrap para el aprovisionamiento de la maquina virtual.

El puppet.conf está en el mismo directorio que el Vagrantfile

[main]
server = puppetserver
certname = puppetserver

[master]
dns_alt_names = puppetserver,puppet

También el bootstrap, llamado aquí server.sh

##### Permite el logueo SSH "normal" #####
sed -i -e "\\#PasswordAuthentication yes# s#PasswordAuthentication yes#PasswordAuthentication no#g" /etc/ssh/sshd_config
systemctl restart sshd.service
#####              #####             #####

#### Instala Puppet Server 5.3 desde Puppetlabs ####    
APT_DOMAIN="//apt.puppetlabs.com"
PCK_PUPPET="puppet5-release-stretch.deb"
PUPPET_DEB="${APT_DOMAIN}/${PCK_PUPPET}"
wget ${PUPPET_DEB}
dpkg -i ${PCK_PUPPET}
apt-get update
apt-get install -y puppetserver 

#### Copia de puppet.conf al directorio de configuración ####
cp -f /home/vagrant/puppet.conf /etc/puppetlabs/puppet/puppet.conf
#### Wilcard de nodos cuyo certificado serán autofirmados ####
echo '*.casa' > /etc/puppetlabs/puppet/autosign.conf

#### Memoria JVM de 2g por defecto a 500 mb  ###
sed -i s/Xmx2g/Xmx500m/g /etc/default/puppetserver;
sed -i s/Xms2g/Xms500m/g /etc/default/puppetserver;
#### Y reinicio del Puppet Server ####
systemctl start puppetserver

Nodos

En un Vagranfile pueden configurarse más de una VM. El script siguiente incluye una función que es llamada para cada máquina que se desee, con distintos nombres para el archivo puppet.conf

def agent(hostname,ip,ssh_key_path,puppet_conf,shell)

  Vagrant.configure("2") do |config|
    config.vm.define hostname do |a|
      a.vm.box = "generic/debian9"
      a.vm.provider "virtualbox"
      a.vm.hostname = hostname
      a.vm.network "public_network",ip: ip, bridge: "enp12s0"
      a.ssh.insert_key = false
      a.ssh.private_key_path = ["~/.vagrant.d/insecure_private_key",ssh_key_path]
      a.vm.provision "file", source: ssh_key_path+".pub", destination: "~/.ssh/authorized_keys"
      a.vm.provision "file", source: puppet_conf, destination: "/home/vagrant/puppet.conf"
      a.vm.provision "shell", path: shell
    end
  end
end

agent("nginx","192.168.1.50","/home/usuario/.ssh/id_rsa","puppet-nginx.conf","agente.sh")
agent("postgres","192.168.1.51","/home/usuario/.ssh/id_rsa","puppet-postgres.conf","agente.sh")

Es muy similar al Vagranfile del servidor. Cabe destacar la llamada:

agent("nginx","192.168.1.50","/home/usuario/.ssh/id_rsa","puppet-nginx.conf","agente.sh").

Lo parametros que se introducen son, en este orden: nombre de la VM y hostname, dirección IP de la máquina, path de la llave RSA, el nombre del archivo puppet.conf y el nombre del archivo bootstrap.

El bootstrap agente.sh para el nodo puede ser como este:

sed -i -e «\#PasswordAuthentication yes# s#PasswordAuthentication yes#PasswordAuthentication no#g» /etc/ssh/sshd_config
systemctl restart sshd.service

echo "192.168.1.90 puppetserver puppet" >> /etc/hosts
wget //apt.puppetlabs.com/puppet5-release-stretch.deb
dpkg -i puppet5-release-stretch.deb
apt-get update
apt-get -y install puppet-agent
cp /home/vagrant/puppet.conf /etc/puppetlabs/puppet/puppet.conf -f
mkdir /var/lib/puppet
ln -s /opt/puppetlabs/puppet/bin/puppet /bin/puppet
puppet agent -t

Y el puppet.conf

[main]
ssldir = /var/lib/puppet/ssl
server = puppetserver
certname = testing-nginx-r0001.casa

[master]
vardir = /var/lib/puppet
cadir  = /var/lib/puppet/ssl/ca
dns_alt_names = puppetserver,puppet

El certname se debe ir cambiando a cada nueva máquina creada si se mantiene el mismo servidor. La razón para ello es que el servidor recibiría la petición de firmar un certificado con un nombre que ya existe y se negaría a hacerlo.

En el ejemplo se usan los archivos de configuración con los nombres puppet-nginx.conf y puppet-postgres.conf entre los cuales la única diferencia de contenido es el certname.

Gustavo Moreno

rocas playa paisaje

Mozilla, novedades de sincronización y privacidad

Compartir recursos con privacidad es una prioridad en muchos profesionales. Las novedades de Mozilla sin duda para muchos serán muy interesantes y son un buen soporte para tareas que, bien entrado el siglo XXI, son cada vez más cotidianas, como compartir notas entre dispositivos y archivos entre usuarios cuidando la privacidad.

Firefox Send, envío privado de archivos

Para quien guste de transferir archivos con la privacidad que merecen, Firefox Send es una solución. Cuando se trata de privacidad, a menudo es muy conveniente configurar un servidor propio para conseguir el servicio. Por ejemplo, Nextcloud con certificado de seguridad, en principio, sería una mejor opción. Sin embargo, no suele ser la primera opción que se considera, ya que requiere su instalación en un servidor y ésta no se trata de una técnica trivial. Por ese motivo, Mozilla acerca a los muchos una solución intermedia, que es utilizar un servicio que no deja de ser de terceros pero que llega desde una organización sin ánimo de lucro y con un historial de trabajo intenso por la libertad en Internet y derechos de los usuarios.

¿Puedo usarlo con Whatsapp?

Sí, pero no de un modo directo. Primero, deberías subir el archivo a //send.firefox.com y, luego, copiar y pegar el enlace que creará automaticamente. El usuario al que le llega el archivo, sólo tendrá que pinchar el enlace

Firefox Send protege el archivo que comparte con una contraseña que desconoce Mozilla. Además, el enlace caduca al llegar a una fecha y número concreto de descargas definidos por el usuario. Es posible usar esta aplicación con o sin registro. El tamaño máximo que se podrá envíar sin registro será 1 gigabyte y con registro 2,5 gigabytes. Estando ya registrado, también sirve para copias de respaldo de datos de Firefox: marcadores, historial, etc…

Pocket, para leer después

Para aquellos momentos de lectura de blogs y documentos web, la aplicación Pocket aportará un repositorio de enlaces con la que, además, podemos leer los contenidos con una estética molona incluso sin conexión. En su versión Android, cuenta con 10 millones de descargas y una valoración media de 4.5 estrellas, por lo que se trata de una app de éxito en el mercado. En su versión para navegador, existe una extensión para Firefox con una valoración media de 4 estrellas con casi 20.000 usuarios.

Firefox Notes

Para aquellas notas que cada vez con más frecuencia deseamos compartir entre varios dispositivos, la extensión Firefox Notes cumple sobradamente. Su app para Android además permite sincronizar pestañas de navegadores entre dispositivos.

protagonistas existenz

Los videojuegos matan a la gente

Una tesis brutal sobre la identidad en un minuto. El anuncio de la Playstation titulado «Doble vida».

El tema de la doble identidad, en un mundo virtual y en el mundo «real», comenzó con los juegos de rol de tablero en los años sesenta del siglo pasado (la década en la que se inventó Internet). Aquellos juegos celebraban entornos virtuales analógicos y novelados immersivos, continuó con los videojuegos «matamarcianos» de los ochenta y eclosionó espectacularmente en la Internet en los noventa y videojuegos que dejaban de ser matamarcianos para contar historias en entornos digitales.

En el relato Snow crash, Neal Stephenson desarrolla, entre otros, el tema de la doble identidad: un programador experto, que trabaja de repartidor de pizzas para la Cosa Nostra, cuando no está trabajando para su empresa, es un héroe legendario en el metaverso, un entorno de realidad virtual en línea al que todo el mundo puede conectarse. Stephenson despliega en el relato una narrativa verosímil sobre un virus informático neurolinguístico de reciente creación y que solo se activa en programadores, provocándoles la muerte instantánea delante del monitor. En la antigüedad, dice unos de los personajes, fue creada la tabla de valores de «el Bien» y «el Mal», génesis de la mentalidad nacionalista, y esta es la dicotonomía básica con la cual los idiomas son divergentes en vez de convergentes. La tabla de valores fue una estrategia de la casta sacerdotal sumeria para modificar las estructuras cerebrales profundas mediante el lenguaje, usándose la poesía sumeria, por una parte, y por la otra, con la ayuda del herpes y el dispositivo de las «prostitutas sagradas», el «hack» cerebral fue propagado como virus. Ergo, la mentalidad dualista son los estragos de un arma biológico-cultural inventada por lo poderosos sumerios.

Desde entonces, la mentalidad dicotómica se ha propagado entre toda la especie y el nuevo virus neurolingüístico en nuestro tiempo, creado por, entre otros, uno de los capos a nivel mundial de los medios de comunicación, amenaza con matar a todos los hackers y programadores del planeta. El objetivo del virus es eliminar a quines pueden oponerse al plan maestro. Una vez despejado el terreno: zombificar, de un modo literal, a toda la especie humana con otro virus más, transmitido por televisión.

El repartidor de pizzas, protagonista del relato, tras presenciar la muerte de un amigo en el metaverso -concretamente, lo que vio morir fue su avatar-, comienza entonces a investigar el virus, en una aventura que le lleva a remotos lugares dentro y fuera del metaverso.

La doble identidad ¿Cuál de las dos era más auténtica? ¿El repartidor de pizzas alienado o el samurai programador que puede morir asesinado y que, con un avatar en un entorno virtual, se enfrenta a una amenaza real para la especie? A medida que el relato se desarrolla, ya no se distinguen ambas identidades, pues lo que el protagonista hace en el metaverso, tiene consecuencias en el mundo analógico, y viceversa.

No suelo exponerme a la televisión, no por temor a que se active un virus mortal en mi mente -creo que aún no se han inventado esa tecnología-, sino porque cada vez que lo hago me regurgita el estómago por perversa. Pero hoy me he expuesto. He visto una noticia que decía que los videojuegos son causa de asesinato, demencias, adicciones a sustancias y no sé cuantas desviaciones más. Sólo puede creerse algo así alguien realmente desinformado sobre el tema o que quiere creérselo por interés (quien gana dinero con las adicciones, cuantas más adicciones haya diagnosticadas, mejor para él). Quizá «criminal» es lo que algunos «adultos» entienden por «juego», quizá les privaron de una infancia o se quedaron cortos de vista por madurar antes de tiempo, y temen los juegos que no sean exclusivamente adultos. La noticia que ví no era sobre los asesinatos; era sobre los videojuegos. El tema básico con el que están jugando con esa campaña mediática es la doble identidad.

Hay dos cuestiones semióticas profundas:

  • Las identidades virtuales que, además, inciden en el mundo real de un modo u otro, están fuera de control. No puede institucionalizarse un mundo imaginario que, además, puede quedar obsoleto antes de ser legislado y ser reemplazado, o ampliado, por otro nuevo. No puede hacerse una gran predicción de cómo y cuando incidirán las redes con identidades virtuales en el mundo analógico. Por ejemplo, las rebeliones que desde el año dos mil se fraguan en Internet (campaña bloguera anti-Sarkozy, Primavera Árabe, el movimiento de los Indignados en España, etc) no fueron previstas y a menudo sus resultados, una vez iniciadas, tampoco lo fueron.
  • La población que no distingue fantasía de deseo es altamente manipulable y pedirá control y más control, para luchar contra el monstruo que cree que lleva dentro. Porque el prejuicio contra los videojuegos, al considerarlos algo de lo que prevenirse, como el sexo para las mentes puritanas, tiene su raíz, además de en la ignorancia, en la incapacidad para discernir fantasía de deseo: ésta, que es la primera regla de cordura. Saltársela también es la causa última sin la cual no serían posibles todas las guerras imperialistas, limpiezas étnicas y persecuciones. El aumento actual de gasto público en militarismo también apunta en este sentido: es preciso que la población demande perder su libertad por miedo a sus propias sombras.

Ahora ya se me hace tarde y voy a descansar, pero mañana toca Starcarft 2: Legacy of The Void, donde la obsesión por la supervivencia y arrasar al enemigo, que excluye otros pensamientos durante la partida, me ayudará a solucionar problemas en mi mente mientras juego. Un juego, nada más. Quizá el temor más profundo de los poderosos es que con juegos tan sofisticados de heurísticas aprenderemos nuevas maneras de aprender a resolver problemas distintas a las que nos enseñaron…. y estaremos fuera de control.

Logo de Docker

Imagen Docker para operaciones con EC2

He creado una primera versión de imagen en Docker para operaciones en Amazon Web Services. La escribí en Ruby e inicio con ella una serie de imágenes Docker para operaciones. Por ahora, tan solo hace las siguientes operaciones. Si pedimos ayuda al propio script:

Usage: ec2.rb [options]

Available options:
    -r, --region REGION              Supply a region
    -c, --create RELATIVE_PATH       Create the file(s) supplied
        --start INSTANCE[s]-ID       Start the INSTANCE[s]-ID supplied
        --stop INSTANCE[s]-ID        Stop the INSTANCE[s]-ID supplied
    -t, --terminate INSTANCE-ID      Terminate the INSTANCE-ID supplied
    -d, --describe                   Describe EC2 instances in region

    -v, --version                    Show version
    -h, --help                       Show this message

Pueden crearse instancias desde plantillas YAML almacenadas en un directorio. La versión es muy pre-alfa y seguramente irá evolucionando el modo de distribuir las plantillas con los dispositivos. Por ahora, consume cualquier archivo .yml en el directorio suministrado al script como parámetro.

La plantilla de ejemplo que incluyo en la imagen:

---
ec2:
  - instance:
    - params:
      - :image_id: 'ami-8fd760f6'
      - :min_count: '1'
      - :max_count: '1'
      - :key_name: 'name'
      - :security_group_ids: 'sg-00000000'
      - :user_data: ''
      - :instance_type: 't2.micro'
      - :placement:
        - :availability_zone: 'eu-west-1a'
      - :subnet_id: 'subnet-00000000'
      - :tag_specifications:
          - :tags:
            - :key: "Name"
            - :value: "Nom1"
  - instance:
    - params:
      - :image_id: 'ami-8fd760f6'
      - :min_count: '1'
      - :max_count: '1'
      - :key_name: 'name'
      - :security_group_ids: 'sg-00000000'
      - :user_data: ''
      - :instance_type: 't2.micro'
      - :placement:
        - :availability_zone: 'eu-west-1a'
      - :subnet_id: 'subnet-00000000'
      - tag_specifications:
          - :tags:
            - :key: "Name"
            - :value: "Nom2"

Referencia: EC2 Create Instances Method

Las credenciales las toma del directorio ~./aws y hay que montar la carpeta en el contenedor (cualquiera con una sugerencia para hacer la compartición de claves más segura será bienvenido/a).

La imagen Docker está aquí.

Asumiendo que tenemos en el directorio instances al menos una plantilla YAML con datos válidos en el mundo real, desde el contenedor Docker podemos crear las instancias de un modo similar a este:

docker run --rm -ti -v ~/.aws:/root/.aws -v ~/ruby-aws/instances:/ec2/instances gustavomrfz/ec2ops-ruby:0.5.1 ruby ec2.rb --create instances

Otras opciones, más obvias, son una descripción de las instancias en la zona de las credenciales, iniciar, apagar varias instancias y terminar una sóla instancia.

Un libro de Docker

Quiza os resulte útil definir un alias como

alias ec2op="docker run --rm -ti -v ~/.aws:/root/.aws -v ~/ruby-aws/instances:/ec2/instances gustavomrfz/ec2ops-ruby:0.5.1 ruby ec2.rb "

y de este modo simplificar el uso del script en la shell:

ec2op --start id-xxxxxxxxxxxx

Github: //github.com/gustavomrfz/ruby-aws

Docker Hub: //hub.docker.com/r/gustavomrfz/ec2ops-ruby/

Luches de coche bajo puente

Despliega manifiestos Puppet en remoto

El objetivo de los scripts en Bash del repositorio que enlaza este artículo es actualizar de manera remota un servidor Puppet 4 con los últimos cambios realizados en la rama master de un repositorio Git. Los scripts se distribuyen en un módulo de Puppet. Las variables de los scripts deberán ser modificadas por el operador para adaptarlas a las necesidades de su entorno.

Sigue leyendo

Abundancia de frutas

Epicuro sobre el bien

«Yo exhorto a placeres continuos y no a esas virtudes vanas y necias que comportan embrolladoras ilusiones de frutos futuros [..] Debemos apreciar lo bello, las virtudes y las cosas por el estilo si es que producen placer; y si no, mandarlas a paseo […] Pues no sé yo que idea puedo hacerme del bien, si suprimo los placeres del gusto, suprimo los de la sexualidad, y suprimo los movimientos placenteros que de las formas bellas recibe la vista»

Epicuro

Sigue leyendo

Virt-builder. Error en dhcpclient-script con blucle infinito

Cuando ejecuto virt-builder en Ubuntu 16.04 aparece un error con el que entra en un bucle:

RTNETLINK answers: File exists
/sbin/dhclient-script: 34: /sbin/dhclient-script: cannot open /etc/fstab: No such file

Puede solucionarse sustituyendo en el script /sbin/dhclient-script la línea:

exec 9>&0 </etc/fstab

Por ésta:

exec 9>&0 </proc/mounts

Entonces, borra el caché de virt-builder:

sudo rm -R .guestfs*

Salud

dependencias puppet

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