Una de las cosas que vi es que aún cuando había configurado los unattended-upgrades y estaba usando Jenkins vía repositorio, cada tanto la versión no estaba actualizada.
Era ingresar y tener la notificación, casi desafiante, acompañada de todos los mensajes que me dejaban claro que algo no funcionaba.
Mientras veía ese mensaje, el footer me mostraba:
El motivo por el cual no se actualizaba se encontraba, básicamente, entre el teclado y la silla.
Al momento de agregar los repositorios de Jenkins y activar los upgrades, al ser aquellos repositorios externos, tengo que indicarle a la actualización que la fuente del repositorio puede ser usada para la actualización desatendida también. (D’oh!)
Para ello, editamos el archivo /etc/apt/apt.conf.d/50unattended-upgrades y habilitamos Jenkins como Allowed-Origins.
El archivo de configuración ahora debería quedar más o menos así:
// Automatically upgrade packages from these (origin:archive) pairs
Unattended-Upgrade::Allowed-Origins {
"${distro_id}:${distro_codename}";
"${distro_id}:${distro_codename}-security";
// Extended Security Maintenance; doesn't necessarily exist for
// every release and this system may not have it installed, but if
// available, the policy for updates is such that unattended-upgrades
// should also install from here by default.
"${distro_id}ESM:${distro_codename}";
"${distro_id}:${distro_codename}-updates";
"o=jenkins.io";
// "${distro_id}:${distro_codename}-proposed";
// "${distro_id}:${distro_codename}-backports";
};
Lo que hicimos fue agregar «jenkins.io:binary»; como origen permitido.
Y eso es todo.
Si quieren estar seguros sobre si las actualizaciones están sucediendo como corresponde, pueden mirar en /var/log/unattended-upgrades/unattended-upgrades.log si todo se actualiza como debe o no.
La segunda parte son los plugins.
También tenía mensajes que demostraban mi error. Por ejemplo:
Actualizar Jenkins no tiene nada que ver con los plugins. Esto es un proceso diferente y va a requerir que creemos un script ya que son 3 pasos que vamos a necesitar ejecutar.
Descargamos la Jenkins CLI, que será la herramienta que nos va a permitir ejecutar comandos en la consola. Se descarga desde tu propia instancia. Para eso agregamos lo siguiente a la URL: /jnlpJars/jenkins-cli.jar.
Es decir que si tu url era jenkins.example.com vamos a descargarlo desde jenkins.example.com/jnlpJars/jenkins-cli.jar (para más info relacionada con la CLI podemos leer también aquí).
Una vez que la descargamos, vamos al segundo paso: en la ubicación que nos sea más cómoda y segura, vamos a crear un archivo que podría ser authentication.txt en donde guardaremos el usuario y contraseña del usuario administrador (o alguno que nos permita actualizar plugins). El formato de la información ha de ser usuario:contraseña.
Supongamos que mi elección es guardar todo en /home/jenkins/, entonces hasta ahora tuve que hacer esto:
wget https://jenkins.example.com/jnlpJars/jenkins-cli.jar /home/jenkins/
Y luego:
echo "usuario:contraseña" >> /home/jenkins/authentication.txt
Ahora vamos a listar los plugins que tengo en mi instancia.
java -jar /home/jenkins/jenkins-cli.jar -s http://127.0.0.1:8080/ -auth @/home/jenkins/authentication.txt list-plugins
Ese comando nos listará todos plugins con información adicional. Algo como:
junit JUnit Plugin 1.32 (1.37)
pipeline-model-extensions Pipeline: Declarative Extension Points API 1.7.1 (1.7.2)
antisamy-markup-formatter OWASP Markup Formatter Plugin 2.1
ssh-slaves SSH Build Agents plugin 1.31.2
workflow-cps-global-lib Pipeline: Shared Groovy Libraries 2.17
pipeline-stage-step Pipeline: Stage Step 2.5
display-url-api Display URL API 2.3.3
matrix-auth Matrix Authorization Strategy Plugin 2.6.2 (2.6.3)
...
Vamos a mejorar ese comando para quitar del medio información que no necesitamos. Ejecutemos ahora:
java -jar /home/jenkins/jenkins-cli.jar -s http://127.0.0.1:8080/ -auth @/home/jenkins/authentication.txt list-plugins | grep -e ')$' | awk '{ print $1 }'
El resultado será:
junit
pipeline-model-extensions
matrix-auth
lockable-resources
pipeline-rest-api
pipeline-model-definition
pipeline-model-api
email-ext
durable-task
Nos toca el tercer paso de la actualización de plugins: ejecutarla. La forma de actualizar un plugin es la siguiente:
java -jar /home/jenkins/jenkins-cli.jar -s http://127.0.0.1:8080/ -auth @/home/jenkins/authentication.txt install-plugin junit
Nótese que junit es el nombre del plugin que tenía primero en mi lista anterior.
Al ejecutar el comando veremos en el siguiente mensaje:
Installing junit from update center
Hacemos un safe restart.
java -jar /home/jenkins/jenkins-cli.jar -s http://127.0.0.1:8080/ -auth @/home/jenkins/authentication.txt safe-restart
Y si listo los plugins como al comienzo, en donde junit estaba en la versión 1.32, tendría que ver esto:
junit JUnit Plugin 1.37
pipeline-model-extensions Pipeline: Declarative Extension Points API 1.7.1 (1.7.2)
antisamy-markup-formatter OWASP Markup Formatter Plugin 2.1
ssh-slaves SSH Build Agents plugin 1.31.2
workflow-cps-global-lib Pipeline: Shared Groovy Libraries 2.17
pipeline-stage-step Pipeline: Stage Step 2.5
...
Tengan presente que puede demorar un poco en reiniciarse el servicio. Si acceden con el navegador, verán la pantalla que los invita a esperar hasta que esté listo.
Dado que todos los pasos fueron ejecutados de la consola estamos en condiciones de automatizarlo (yey!).
Llevemos esto a un script.
#!/bin/bash
UPDATE_LIST=$( java -jar /home/jenkins/jenkins-cli.jar -s http://127.0.0.1:8080/ -auth @/home/jenkins/authentication.txt list-plugins | grep -e ')$' | awk '{ print $1 }' );
if [ ! -z "${UPDATE_LIST}" ]; then
java -jar /home/jenkins/jenkins-cli.jar -s http://127.0.0.1:8080/ -auth @/home/jenkins/authentication.txt install-plugin ${UPDATE_LIST}
java -jar /home/jenkins/jenkins-cli.jar -s http://127.0.0.1:8080/ -auth @/home/jenkins/authentication.txt safe-restart
fi
He quitado la descarga de la CLI porque no debe hacerse siempre. Si quisiéramos descargarla sólo cuando corresponda necesitaremos hacer un script que valide la versión instalada y la última versión estable para que sepamos si deberíamos descargarla (y no estar descargando siempre el mismo archivo); pero para eso necesitamos algo un poquito más sofisticado.
También pueden evitar descargar la consola cada vez y poner un script independiente que lo haga una vez por mes (por decir algo). Aquí cada uno deberá buscar qué le funciona mejor.
Ahora si, de esta forma debería poder estar un poco más tranquilo sabiendo que tanto Jenkins como sus plugins se mantendrán actualizados.
Es necesario recordar la necesidad de revisar los logs ya que podríamos encontrarnos, en algún punto, con alguna falla o un servicio no disponible. Otra vez, cada uno deberá evaluar qué tanto valor aporta la automatización.
En mi caso, es más importante que esté siempre actualizado. Cuando falle, me dedicaré a mirar qué se pudo haber roto.
Actualmente uso dos scripts que se encargan del tema y me notifican sobre lo que sucede.
O si hay actualización de algún plugin:
Creo que vale la pena recordar/repetir que confiar o no en la actualización automática será algo que deberán medir en base a la capacidad de monitorear y actualizar manualmente. Podría darse el caso en el cual un update automático rompa algo y la cura sea peor que la enfermedad. En mi caso, por ahora, no ha sido un problema y recrear la instancia me resulta bastante rápido.