From bd2c740c8c028743f1f62fea5258640788851ba7 Mon Sep 17 00:00:00 2001
From: Varac <varac@varac.net>
Date: Sun, 5 Feb 2023 20:48:26 +0100
Subject: [PATCH] Migrate to waybar

---
 README.md                                     |  11 ++-
 alertmanager_status.py                        |  66 ++++++++++++++++
 .../prometheus-green.svg                      |   0
 prometheus.svg => img/prometheus.svg          | Bin 33843 -> 33835 bytes
 tray-example.png => img/tray-example.png      | Bin
 indicator_alertmanager.py => indicator.py     |  14 ++--
 query_alertmanager.py                         |  71 ------------------
 7 files changed, 80 insertions(+), 82 deletions(-)
 create mode 100755 alertmanager_status.py
 rename prometheus-green.svg => img/prometheus-green.svg (100%)
 rename prometheus.svg => img/prometheus.svg (51%)
 rename tray-example.png => img/tray-example.png (100%)
 rename indicator_alertmanager.py => indicator.py (94%)
 delete mode 100755 query_alertmanager.py

diff --git a/README.md b/README.md
index 4262fab..fd110ab 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,13 @@
-# Alertmanager indicator
+# Alertmanager status
 
-Tray icon for [alertmanager](https://prometheus.io/docs/alerting/latest/alertmanager/), based on [libappindicator](https://launchpad.net/libappindicator).
+`./alertmanager_status.py` will output the [alertmanager](https://prometheus.io/docs/alerting/latest/alertmanager/)
+status details in a [waybar](https://github.com/Alexays/Waybar) compatible
+JSON format.
+
+It also holds a historic `indicator.py` python class for a tray icon
+based on [libappindicator](https://launchpad.net/libappindicator). I don't use
+it anymore and it doesn't work in the current state, although it might be
+easy to get it working again.
 
 ![tray icon example](./tray-example.png)
 
diff --git a/alertmanager_status.py b/alertmanager_status.py
new file mode 100755
index 0000000..4190e4b
--- /dev/null
+++ b/alertmanager_status.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python3
+"""
+Alertmanager status applet using appindicator.
+"""
+
+import json
+import os
+from pathlib import Path
+import plac
+import yaml
+from query_alertmanager import get_alerts
+
+
+def show_alerts(opts):
+    """Show alerts."""
+    alerts = get_alerts(url=opts["url"],
+                        port=opts["port"],
+                        user=opts["user"],
+                        password=opts["password"])
+
+    # Construct waybar output
+    # https://github.com/Alexays/Waybar/wiki/Module:-Custom#return-type
+    # {"text": "$text", "alt": "$alt", "tooltip": "$tooltip",
+    #  "class": "$class", "percentage": $percentage }.
+    # This means the output should also be on a single line
+    output = {}
+    output["text"] = alerts['summary']
+    if alerts['summary'] == "Cant connect":
+        output["alt"] = "error"
+        output["tooltip"] = "Some error occurred."
+    else:
+        if alerts["count"] > 0:
+            output["alt"] = "firing"
+            output["tooltip"] = '\n'.join(alerts['alerts'])
+        else:
+            output["alt"] = "snafu"
+            output["tooltip"] = "Situation normal, all fucked up 😃"
+    print(json.dumps(output))
+
+
+@plac.opt('configpath', "Path to alertmanager config", type=Path)
+@plac.opt('mode', "Mode: wayland or indicator (not working)", type=str)
+@plac.flg('debug', "Enable debug mode")
+def main(configpath='~/.config/indicator_alertmanager/config.yml',
+         mode="wayland"):
+    """Main function."""
+
+    # Load config
+    with open(Path.expanduser(configpath), encoding="UTF8") as config_file:  # type:ignore
+        opts_raw = yaml.load(config_file, Loader=yaml.FullLoader)
+        opts = {}
+        opts["url"] = opts_raw.get('url')
+        opts["port"] = opts_raw.get('port', 443)
+        opts["user"] = opts_raw.get('user', 'admin')
+        opts["password"] = opts_raw.get('password')
+        opts["icon_red"] = os.path.abspath("./prometheus.svg")
+        opts["icon_green"] = os.path.abspath("./prometheus-green.svg")
+
+    if mode == "wayland":
+        show_alerts(opts)
+    # if mode == "indicator":
+        # Indicator()
+
+
+if __name__ == "__main__":
+    plac.call(main)
diff --git a/prometheus-green.svg b/img/prometheus-green.svg
similarity index 100%
rename from prometheus-green.svg
rename to img/prometheus-green.svg
diff --git a/prometheus.svg b/img/prometheus.svg
similarity index 51%
rename from prometheus.svg
rename to img/prometheus.svg
index b931fe76dd4b907b095e49f7d77c37fbfbfbcfd9..ccce45fcf39cdd9dfd8719286bcb36beef4ed19d 100644
GIT binary patch
delta 969
zcmdno!L+)AiMunv&z(z(i-CcGYa@?36C>AV6DCPUMy}0%%+pyIxi&vzHv;h_IfX%#
zF4qB&l6O42nKifq_yU4z-!AukJNwTAu6JdInGDJa-xhoLXdRkR#4x2@YI5C;>$iSz
zO};4bosnzuNkLOauFd}i6IdC!HYbYnfs8AVc*4lYH91tOl#y%mX{qHPvx{XN7=^gZ
z_nR!sx1H_r<2={)a}`JXxi%k_I|oubMZtLU2?ZgL?%RsSOpIKU`Bk(Sxh7kw6fkma
zUafK%B$Thdmyv6-u0|&#*W~RQxr|(!RW)Nkx|_6&#JFtkEU~G(EuZ#i-tk6h#v4m}
zcoc%THlNlKXJO=;{8;ZgBiH2J`sR#WlRxXLF>+0oGVo&L+MH@o%*?^{@9h?)&ri8F
zKQI;t+4I9RiIHn^w3!kk*XBC2aAroX&DSh7Ko<SCn#9Ppd6IQI<76pYS!u3`ECEGd
zXGi<l8VWsi2>VgJnrVW{+tv3CE4elY*}8)KJ;OepNr&sp3uivLf+q|bja=#HSE{ix
ze9U5(6JQd!dNsIGi~X1>yMw0BDz5-Oh9g{)m7Q)eadB<_@AR38lS}6d>k@_|Wn7d0
zxOOvgZSHVu0J(<KO9A8>EpJ^$uE`PJ3XEKvE4}5|8M!vk2#N<O_z|iC3QE~<CXjy=
zB6}IRHm{3R1ZlbuCCSJ&`Bl^gMy}1XqfHr^xu$S!z8oV6QvWpeIEY#s{|uyZN@6G@
z*XCD=4$O>PleJSpk-0E6oRNu(Yx1wO6O3Gw52vRwa&6YiP+=70ntS*D^xOU(ObiSQ
z4DP&L%QZPZ(~yyC^2E#(My|=<GWRobZQhop1ai&IoC-#+$w9d}j9ioV=l)^jn!Gn}
z8za}|lKiV6TfGWx8M!8R6dq;dn(SAk#K<+duxO$ZC{>2k=Jw_nUN=8to}jVj^lR(t
zdkO6C&T<{O)c5VDJJ)2@;%H$ml}3wKx9xs#&5Uyq(s*F@NsDXq<YG{woV=*Sjgf2e
z%aVPJT$@*vIx<RfH6LL-#c1Hft{?Vq+mg;DjW&5t<tDvh=Gx3ut`BmFQH3ib*W`+d
zTt=?R&nmVsa!sCHIbV!x=Ff29M!Tb>E(}i@L{q%IA9J7m!nHY|sv4x{Om#LR*JO*D
z?QC2{|5xzYO#W7Ln2~Gpu3At?Db_6jC5b}~;6y9mRKm&Cc=P_@hmBlZljk(4Fmg>k
P*woC(HQBZK9U~V2M!rqu

delta 986
zcmZ48!L+%9iKjEb&z+Y`ii?4Pfp;UfIuj%BW@9EvMn>MvzRc5E7<o58Wj6xxBshgZ
zln&Pckdn7NyO}k31NZ`hYTqvReLMTl1KxLKhM5e?3Evib_-GxPP{c5$U21aOjqA65
z@J_xU@STx&@(DpxM&8Z;1QS@96nHnsi}QiZ%aeG*$jCc6SgMqfck@Z9<sicgWgQrW
zc+K~lEX%i@?eXJ0*Y<N2NBem<AC@}@Qaee(n2~4mQ3WB8{u_$MOpLsfc~rC*c_*8z
z6fp8`UZHXrB$T7Rmyvg}mPRKd@8m5Sxs1G<l{8~O`s=lf7!@XO)DmUn-F#e2oQ08h
z@_oJQjJ%V#>zgz3PJXYi#>hKa%)pD0cXOgaF*676zqebIK0oE%e8*TEWbhZ$Bu3uJ
z;buyVyql}c!kHO)H(#>U0Ga&TY7!&w=059oMoR^*&&=@xGm8>#-q{?f<gjs{6vsaw
z4u(aG@=op8t;#!*C7|f*>}Wq*L!qY*VLz%@Gfhx=yZXLiCGTcmTUSsZOtz0_;^F=B
z!kJI5;0c39Bk$yYj`EDWljWRlG4b+l{^j(UiA#Y?=L_o+h9hOXlfSukGxBb3a%%uN
zhuKR3<Qx@mT_xVRGbexgB`vP~;`|c7uoah`w=bXh@@3InEltmR?VH<vSMqKy_LgI3
z<lQ_eC?2HuQ>Y3kT*bqgKz@~q>;;8rq#~m<??xX1bG^BjuV4C6Hi>~j=8k@ZZ_*DV
zPk%Mu$xos-F!FAm8g0tR%sYj5^Vt|dkQw)5kAtY?@y|f6=}Qb{<lX!v(Sezfcd}|K
zD86T>hBGqp@=pGec7l<2^4|0`M&8XT87ho|ymRl~pMKllgNcD*fx(@(Yk4O}W*Rc`
zPVUZ3VdS0sA#*<?@8%6zN+1_r&Z%JJo$QmF!^k^%XYL;+1>VWq^0qPZZqCiW3bNL@
z(3X*Ra%169M&8NpMM{jkle3B@GAc~|T_nZ9d*o8zx1a93lVyveg?UvPEneNW`@uUi
z&P7P$f!QZ5-p$>`phP-(R*4%U@8pLi`xtpQFDP|nl;mwb!gz|&z=>Ty?BBK}ol6>R
z@}9~~dc(}S`B#}f$X2ZiS4Q5+1r@oByp!)$Y+>Y`Jh^hd81KxV;lhn}M@wB8o-&B0
zczZwQKKq4tvqx1mNY9b#Y)0P61~uE+d5iw9;ImPf{I=#WBk$ymwV-g3s9OL^7CRfj
kX;`eOgp;@N=KaGD8+myrPi|6S<ej{ushN>?vQ6_l0K!&V5C8xG

diff --git a/tray-example.png b/img/tray-example.png
similarity index 100%
rename from tray-example.png
rename to img/tray-example.png
diff --git a/indicator_alertmanager.py b/indicator.py
similarity index 94%
rename from indicator_alertmanager.py
rename to indicator.py
index 6d1ff58..e4d4066 100755
--- a/indicator_alertmanager.py
+++ b/indicator.py
@@ -1,20 +1,22 @@
 #!/usr/bin/env python3
 """
 Alertmanager status applet using appindicator.
+
+Install dependencies (`libffi7` is needed by `pygobject`):
+
+  sudo apt install gir1.2-appindicator3-0.1 libffi7
 """
 
-# import json
 import os
 from pathlib import Path
-import signal
 import time
 from threading import Thread
 
 import plac
 import gi
 import yaml
-from gi.repository import Gtk, AppIndicator3, GLib  # type: ignore
 from query_alertmanager import get_alerts
+from gi.repository import Gtk, AppIndicator3, Glib  # type: ignore
 gi.require_version('Gtk', '3.0')
 gi.require_version('AppIndicator3', '0.1')
 
@@ -103,9 +105,3 @@ class Indicator():
     def stop(self):
         """Exit indicator."""
         Gtk.main_quit()
-
-
-if __name__ == "__main__":
-    plac.call(Indicator)
-    signal.signal(signal.SIGINT, signal.SIG_DFL)
-    Gtk.main()
diff --git a/query_alertmanager.py b/query_alertmanager.py
deleted file mode 100755
index d14d6bb..0000000
--- a/query_alertmanager.py
+++ /dev/null
@@ -1,71 +0,0 @@
-#!/usr/bin/env python3
-"""Queries alertmanager for alerts, outputs json.
-
-Can be also used as cli application.
-Usage:
-
-  ./query_alertmananger.py -h
-"""
-
-import json
-import plac
-import requests
-from alertmanager import AlertManager
-
-
-def get_alerts(url, password, port=443, user='admin'):
-    req = requests.Session()
-    req.auth = (user, password)
-    AM = AlertManager(host=url, port=port, req_obj=req)
-
-    count = 0
-    alerts = []
-    state = "unknown"
-
-    try:
-        alerts_raw = AM.get_alerts()
-        for alert in alerts_raw:
-            name = alert['labels']['alertname']
-            severity = alert['labels']['severity']
-            instance = alert['labels']['instance']
-            alert_state = alert['status']['state']
-            release_name = alert['labels']['release_name']
-
-
-            if severity != "none" and alert_state != "suppressed":
-                count += 1
-                alert_text = f'{name}: {instance}, {release_name} ({severity})'
-                alerts.append(alert_text)
-
-        if count > 2:
-            state = "critical"
-        elif count > 0:
-            state = "warning"
-        elif count == 0:
-            state = "ok"
-
-        summary = f'{count} alerts'
-    except:
-        summary = "Cant connect"
-        state = "warning"
-
-    return_data = {
-        'summary': summary,
-        'alerts': alerts,
-        'state': state,
-        'count': count }
-    return return_data
-
-
-@plac.opt('url', "URL of alertmanager instance", type=str, abbrev='U')
-@plac.opt('port', "Port of alertmanager instance", type=int, abbrev='P')
-@plac.opt('user', "User name", type=str)
-@plac.opt('password', "Password", type=str)
-def main(url, password, port=443, user='admin'):
-    """Main function."""
-    alerts = get_alerts(url=url, password=password, port=port, user=user)
-    print(json.dumps(alerts))
-
-
-if __name__ == '__main__':
-    plac.call(main)
-- 
GitLab