Gotify est un serveur de notification en Go. Il permet de lui envoyer via une API du json avec une simple requête curl ou depuis du code.
Il propose une interface web pour créer des applications qui génère une token nécessaire à l’envoi des messages mais surtout une application android. Ainsi on pourra recevoir sur son téléphone des alertes et notifications envoyées par ses scripts et programmes.
L’idée est ici de l’utiliser pour l’ajouter dans un pipeline Drone afin d’être notifié du statut d’un déploiement. Jusqu’à présent j’utilisais Telegram (voir l’article un plugin drone pour telegram) cependant imposer une messagerie n’est pas forcément l’idéal dans tous les cas. De plus l’interface web de Gotify peut être utilisée comme moniteur des déploiements.
La première étape est de créer une image Docker car il n’y en a pas pour ARM64. Le développeur propose un binaire ARM64 ce qui simplifie le Dockerfile
cat Dockerfile.arm64v8
FROM arm64v8/debian:stable-slim
ADD https://github.com/gotify/server/releases/download/v2.0.5/gotify-linux-arm64.zip /
RUN apt-get update &&\
apt-get install -y unzip &&\
unzip /gotify-linux-arm64.zip -d /
EXPOSE 80
ENTRYPOINT ["/gotify-linux-arm64"]
Le docker compose
cat gotify-arm64v8.yml
version: "3"
services:
gotify:
image: fredix/arm64v8-gotify:2.0.5
env_file: .env.production-server
networks:
- traefik-net
ports:
- 80
volumes:
- /swarm/volumes/gotify:/app/data
deploy:
placement:
constraints:
- node.labels.location == cloud-arm64
labels:
- "traefik.port=80"
- "traefik.docker.network=traefik-net"
- "traefik.frontend.rule=Host:gotify.fredix.xyz"
networks:
traefik-net:
external: true
le fichier .env.production-server contient les variables d’environnement qui servent à configurer le serveur. J’ai choisi sqlite mais si de nombreuses notifications sont prévues il vaut sans doute mieux utiliser un SGBD.
cat .env.production-server
GOTIFY_DATABASE_DIALECT=sqlite3
GOTIFY_DATABASE_CONNECTION=gotify.db
GOTIFY_DEFAULTUSER_NAME=fredix
GOTIFY_DEFAULTUSER_PASS=PASS
GOTIFY_PASSSTRENGTH=10
GOTIFY_UPLOADEDIMAGESDIR=images
GOTIFY_PLUGINSDIR=plugins
on lance la stack
docker stack deploy --compose-file=gotify-arm64v8.yml gotify-arm64
l’interface permet de créer des utilisateurs et des applications.
On test que tout fonctionne avec un curl
curl -X POST "https://gotify.fredix.xyz/message?token=TOKEN" -F "title=test"
-F "message=hello world" -F "priority=5"
{"id":21,"appid":1,"message":"hello world","title":"test","priority":5,"date":"2019-06-09T19:02:03.800809406Z"}%
Et sur android
Le marketplace de Drone ne proposant pas de plugin Gotify j’en ai développé un rapidement en Go : drone-gotify, l’image ARM64v8 est sur le hub docker : fredix/arm64v8-alpine-drone-gotify. L’exemple de code Go fait 2 lignes : https://gotify.net/docs/more-pushmsg#golang, celui pour Drone fait à peine plus : https://docs.drone.io/plugins/examples/golang/. Le code suivant fait donc le boulot
package main
import (
"net/http"
"net/url"
"os"
"log"
)
func main() {
token := os.Getenv("PLUGIN_GOTIFYTOKEN")
endpoint := os.Getenv("PLUGIN_GOTIFYENDPOINT")
title := os.Getenv("PLUGIN_GOTIFYTITLE")
message := os.Getenv("PLUGIN_MESSAGE")
priority := os.Getenv("PLUGIN_GOTIFYPRIORITY")
resp, err := http.PostForm(endpoint + "/message?token=" + token, url.Values{"message": {message}, "title": {title}, "priority": {priority}})
if resp != nil {
resp.Body.Close()
}
if err != nil {
log.Fatalln(err)
}
}
Pour l’utiliser voici le step a mettre dans le pipeline .drone.yml. A noter que j’utlise les secret Drone.
- name: gotify
image: fredix/arm64v8-alpine-drone-gotify
settings:
gotifytoken:
from_secret: plugin_gotifytoken
gotifyendpoint:
from_secret: plugin_gotifyendpoint
gotifytitle:
from_secret: plugin_gotifytitle
gotifypriority:
from_secret: plugin_gotifypriority
message: >
{{#success build.status}}
build {{build.number}} succeeded on {{repo.name}}. Good job {{build.author}} {{build.link}}
{{else}}
build {{build.number}} failed on {{repo.name}}. Fix me please {{build.author}} {{build.link}}
{{/success}}
when:
status: [ success, failure ]
A savoir, au risque de perdre du temps, que Drone passe ces variables d’environnement au conteneur en ajoutant PLUGIN_. Dans le .drone.yml il ne faut donc pas mettre PLUGIN_GOTIFYTOKEN mais gotifytoken (Drone semble insensible à la casse).
Le problème de ce code est que l’on va recevoir la notification de manière brute. En effet le message est un template et il ne sera pas interprété, on va donc recevoir :
{{#success build.status}}
build {{build.number}} succeeded on {{repo.name}}. Good job {{build.author}} {{build.link}}
{{else}}
build {{build.number}} failed on {{repo.name}}. Fix me please {{build.author}} {{build.link}}
{{/success}}
ce qui est assez inutile.. J’ai ajouté du code du plugin google chat pour que le template soit interprété. Après un déploiement on reçoit une jolie notification sur l’interface web et le smartphone.
Cet outil ouvre toutes sortes de perspectives comme des alertes de monitoring ou l’envoi de messages depuis des rapsberry pi.
Installer un serveur de notifications push Gotify
Deploying A Self-Hosted Portable Notification Service