Browse Source

new: [0km] add ``vps-subscribe {add,rm} CHANNEL TOPICS`` actions

pull/8/head
Valentin Lab 9 months ago
parent
commit
9f0b9908c8
  1. 96
      README.org
  2. 191
      bin/0km

96
README.org

@ -1165,6 +1165,102 @@ suivants: =mailcow=, =postfix=, =rspamd=, =redis=, =crypt=, =vmail=,
0km vps-backup recover myadmin@core-06.0k.io:10023#mail.mybackupedvps.com:postfix mynewvps.com
#+end_src
** Usage de l’alerting
Une commande ~send~ est fourni pour envoyer des alertes via [[https://docs.ntfy.sh/][ntfy]], et
par défaut, enverra ces notifications sur http://ntfy.0k.io .
Par défaut, le VPS dispose d'un topic qui lui est propre (et surlequel
il a les droits de publication). Et il est possible de rediriger les
différent type de notification vers les topics que l'on souhaite pour
permettre une administration de ces VPS.
Donc, pour les admin, via la commande ~0km vps-subscribe~, on pourra
facilement gérer l'addition de nouveau topic et en même temps
s'assurer de donner les droit au VPS de publication sur ces topics.
*** Commande ~send~
Sur le VPS, la commande ~send~ permet d’envoyer un message sur un ou
plusieurs topics. (voir ~send --help~ pour plus d’info). La fonction
envoie un message sur un channel, et ce message est envoyé à tous les
topics associés à ce channel.
**** Configuration du serveur de notification
La configuration du serveur de notification et les identifiant unique
du VPS sont dans le fichier ~/etc/ntfy/ntfy.conf~.
**** Configuration des topics
La configuration des channels/topics est faite dans le fichier
~/etc/ntfy/topics.yml~.
Exemple:
- Configuration par défaut
#+begin_src yaml
.*\.(emerg|alert|crit|err|warning|notice):
- ${LOGIN}_main
#+end_src
On pourra utiliser:
#+begin_src sh
send -c backup.crit "no backup done in 24h"
#+end_src
qui sera notifié sur le serveur =ntfy= de la configuration en cours, dans le
topic ~${LOGIN}_main~. Ainsi que tout autre message dans les channels se terminant
par ~.emerg~, ~.alert~, ... etc...
- Configuration spécifique
#+begin_src yaml
.*\.alert:
- elabore_alert
#+end_src
Si on **ajoute** la précédente configuration, la commande suivante:
#+begin_src sh
send -c disk.alert "no space left"
#+end_src
... va envoyer le message aussi bien au précédent topic
~${LOGIN}_main~, mais aussi au topic ~elabore_alert~ car il se
termine par ~.alert~.
-
#+begin_src yaml
main:
- maintenance
- debug_foo
- ${LOGIN}_main
#+end_src
La commande:
#+begin_src sh
send -c main "no space left"
#+end_src
.. enverra sur les topics ~maintenance~ et ~debug_foo~ et
~${LOGIN}_main~ (qui est un topic créé pour le VPS par défaut).
*** Ajouter/Enlever des droits d’écriture sur les topics
Sur un poste d'admin (via la commande ~0km~), et après avoir demandé
un accès au serveur ntfy de destination (une clé SSH sera nécessaire),
on pourra utiliser la sous-commande ~0km vps-subscribe~.
#+begin_src sh
## Ajouter
0km vps-subscribe add CHANNEL TOPIC VPS
## Enlever
0km vps-subscribe rm CHANNEL TOPIC VPS
#+end_src
** Troubleshooting

191
bin/0km

@ -656,6 +656,156 @@ EOF
}
NTFY_TOPIC_FILE="/etc/ntfy/topics.yml"
NTFY_CONFIG_FILE="/etc/ntfy/ntfy.conf"
subscribe:ntfy:topic-file-exists() {
local vps="$1"
if ! out=$(echo "[ -f \"$NTFY_TOPIC_FILE\" ] && echo ok || true" | \
ssh:run "root@$vps" -- bash); then
err "Unable to check for existence of '$NTFY_TOPIC_FILE'."
fi
if [ -z "$out" ]; then
err "File '$NTFY_TOPIC_FILE' not found on $vps."
return 1
fi
}
subscribe:ntfy:config-file-exists() {
local vps="$1"
if ! out=$(echo "[ -f \"$NTFY_CONFIG_FILE\" ] && echo ok || true" | \
ssh:run "root@$vps" -- bash); then
err "Unable to check for existence of '$NTFY_CONFIG_FILE'."
fi
if [ -z "$out" ]; then
err "File '$NTFY_CONFIG_FILE' not found on $vps."
return 1
fi
}
ntfy:rm() {
local channel="$1" topic="$2" vps="$3"
subscribe:ntfy:topic-file-exists "$vps" || return 1
if ! out=$(echo "yq -i 'del(.[\"$channel\"][] | select(. == \"$TOPIC\"))' \"$NTFY_TOPIC_FILE\"" | \
ssh:run "root@$vps" -- bash); then
err "Failed to remove channel '$channel' from '$NTFY_TOPIC_FILE'."
return 1
fi
info "Channel '$channel' removed from '$NTFY_TOPIC_FILE' on $vps."
ssh:run "root@$vps" -- cat "$NTFY_TOPIC_FILE"
}
ntfy:add() {
local channel="$1" topic="$2" vps="$3"
vps_connection_check "$vps" </dev/null || return 1
subscribe:ntfy:topic-file-exists "$vps" || return 1
if ! out=$(echo "yq '. | has(\"$channel\")' \"$NTFY_TOPIC_FILE\"" | \
ssh:run "root@$vps" -- bash); then
err "Failed to check if channel '$channel' with topic '$topic' is already in '$NTFY_TOPIC_FILE'."
return 1
fi
if [ "$out" != "true" ]; then
## Channel does not exist
if ! out=$(echo "yq -i '.[\"$channel\"] = []' \"$NTFY_TOPIC_FILE\"" | \
ssh:run "root@$vps" -- bash); then
err "Failed to create a new channel '$channel' entry in '$NTFY_TOPIC_FILE'."
return 1
fi
else
## Channel exists
if ! out=$(echo "yq '.[\"$channel\"] | any_c(. == \"$topic\")' \"$NTFY_TOPIC_FILE\"" | \
ssh:run "root@$vps" -- bash); then
err "Failed to check if channel '$channel' with topic '$topic' is already in '$NTFY_TOPIC_FILE'."
return 1
fi
if [ "$out" == "true" ]; then
info "Channel '$channel' with topic '$topic' already exists in '$NTFY_TOPIC_FILE'."
return 0
fi
fi
if ! out=$(echo "yq -i '.[\"$channel\"] += [\"$topic\"]' \"$NTFY_TOPIC_FILE\"" | \
ssh:run "root@$vps" -- bash); then
err "Failed to add channel '$channel' with topic '$topic' to '$NTFY_TOPIC_FILE'."
return 1
fi
info "Channel '$channel' added with topic '$topic' to '$NTFY_TOPIC_FILE' on $vps."
}
NTFY_BROKER_SERVER="ntfy.0k.io"
ntfy:topic-access() {
local action="$1" topic="$2" vps="$3"
subscribe:ntfy:config-file-exists "$vps" || return 1
local user
user=$(ntfy:get-login "$vps") || return 1
case "$action" in
"write")
ssh "ntfy@$NTFY_BROKER_SERVER" "topic-access" \
"$user" "$topic" "write-only" </dev/null || {
err "Failed to grant write access to '$user' for topic '$topic'."
return 1
}
info "Granted write access for '$user' to topic '$topic'."
;;
"remove")
ssh "ntfy@$NTFY_BROKER_SERVER" "topic-access" -r "$user" "$topic" </dev/null || {
err "Failed to reset access of '$user' for topic '$topic'."
return 1
}
info "Access for '$user' to topic '$topic' was resetted successfully."
;;
*)
err "Invalid action '$action'."
return 1
;;
esac
}
ntfy:get-login() {
local vps="$1"
if ! out=$(echo ". \"$NTFY_CONFIG_FILE\" && echo \"\$LOGIN\"" | \
ssh:run "root@$vps" -- bash); then
err "Failed to get ntfy login from '$NTFY_CONFIG_FILE'."
return 1
fi
if [ -z "$out" ]; then
err "Unexpected empty login retrieved from sourcing '$NTFY_CONFIG_FILE'."
return 1
fi
echo "$out"
}
subscribe:add() {
local vps="$1"
read-0 channel topic || {
err "Couldn't read CHANNEL and TOPIC arguments."
return 1
}
vps_connection_check "$vps" </dev/null || return 1
ntfy:topic-access "write" "$topic" "$vps" </dev/null || return 1
ntfy:add "$channel" "$topic" "$vps" || {
err "Failed to add channel '$channel' with topic '$topic' to '$NTFY_TOPIC_FILE'."
echo " Removing topic access." >&2
ntfy:topic-access "remove" "$topic" "$vps" </dev/null
return 1
}
}
subscribe:rm() {
local vps="$1"
read-0 channel topic || {
err "Couldn't read CHANNEL and TOPIC arguments."
return 1
}
vps_connection_check "$vps" </dev/null || return 1
ntfy:rm "$channel" "$topic" "$vps" || return 1
ntfy:topic-access "remove" "$topic" "$vps" </dev/null || {
err "Failed to remove topic access for '$topic' on '$vps'."
return 1
}
}
vps_backup_recover() {
local vps="$1" admin server id path rtype force type
@ -1619,4 +1769,45 @@ graph:def:load_avg() {
}
cmdline.spec.gnu vps-subscribe
cmdline.spec::cmd:vps-subscribe:run() {
:
}
cmdline.spec.gnu add
cmdline.spec:vps-subscribe:cmd:add:run() {
: :posarg: CHANNEL 'Channel which will be sent to given topic'
: :posarg: TOPIC 'Ntfy topic to recieve messages of given channel
(format: "[MYSERVER:]MYTOPICS"
Examples: "ntfy.0k.io:main,storage,alerts",
"main{1,3,7}"
)'
: :posarg: [VPS...] 'Target host(s) to get stats'
printf "%s\0" "$CHANNEL" "$TOPIC" |
vps_mux subscribe:add "${VPS[@]}"
}
cmdline.spec.gnu rm
cmdline.spec:vps-subscribe:cmd:rm:run() {
: :posarg: CHANNEL 'Channel which will be sent to given topic'
: :posarg: TOPIC 'Ntfy topic to recieve messages of given channel
(format: "[MYSERVER:]MYTOPICS"
Examples: "ntfy.0k.io:main,storage,alerts",
"main{1,3,7}"
)'
: :posarg: [VPS...] 'Target host(s) to get stats'
printf "%s\0" "$CHANNEL" "$TOPIC" |
vps_mux subscribe:rm "${VPS[@]}"
}
cmdline::parse "$@"
Loading…
Cancel
Save