Subject: [bug#40738] [PATCH 4/4] services: Add a service for Alertmanager.

From: Christopher Baines <[email-masked]>
Date: Mon, 20 Apr 2020 22:17:43 +0100

---
 gnu/services/monitoring.scm | 82 +++++++++++++++++++++++++++++++++++++
 gnu/tests/monitoring.scm    | 71 ++++++++++++++++++++++++++++++++
 2 files changed, 153 insertions(+)

diff --git a/gnu/services/monitoring.scm b/gnu/services/monitoring.scm
index a37dfd80d8..50a4b7302c 100644
--- a/gnu/services/monitoring.scm
+++ b/gnu/services/monitoring.scm
@@ -51,6 +51,17 @@
             prometheus-configuration-storage-tsdb-path
             prometheus-configuration-extra-options
 
+            alertmanager-service-type
+            <alertmanager-configuration>
+            alertmanager-configuration
+            alertmanager-configuration-package
+            alertmanager-configuration-user
+            alertmanager-configuration-group
+            alertmanager-configuration-config-file
+            alertmanager-configuration-web-listen-address
+            alertmanager-configuration-storage-path
+            alertmanager-configuration-extra-options
+
             zabbix-server-configuration
             zabbix-server-service-type
             zabbix-agent-configuration
@@ -226,6 +237,77 @@ prometheus.")
            (compose list prometheus-node-exporter-shepherd-service))))
    (default-value (prometheus-node-exporter-configuration))))
 
+
+;;;
+;;; Alertmanager
+;;;
+
+(define-record-type* <alertmanager-configuration>
+  alertmanager-configuration
+  make-alertmanager-configuration
+  alertmanager-configuration?
+  (package            alertmanager-configuration-package
+                      (default alertmanager))
+  (user               alertmanager-configuration-user
+                      (default "alertmanager"))
+  (group              alertmanagerconfiguration-group
+                      (default "alertmanager"))
+  (config-file        alertmanager-config-file
+                      (default (plain-file "alertmanager.yml" "")))
+  (web-listen-address alertmanager-web-listen-address
+                      (default ":9093"))
+  (storage-tsdb-path  alertmanager-storage-tsdb-path
+                      (default "/var/lib/alertmanager/data/"))
+  (extra-options      alertmanager-configuration-extra-options
+                      (default '())))
+
+(define alertmanager-shepherd-service
+  (match-lambda
+    (($ <alertmanager-configuration> package user group
+                                   config-file web-listen-address
+                                   storage-tsdb-path extra-options)
+     (shepherd-service
+      (documentation "Alertmanager monitoring system and time series database.")
+      (provision '(alertmanager))
+      (requirement '(networking))
+      (start #~(make-forkexec-constructor
+                (list #$(file-append package "/bin/alertmanager")
+                      "--config.file" #$config-file
+                      "--web.listen-address" #$web-listen-address
+                      "--storage.path" #$storage-tsdb-path
+                      #$@extra-options)
+                #:user #$user
+                #:group #$group
+                #:log-file "/var/log/alertmanager.log"))
+      (stop #~(make-kill-destructor))))))
+
+(define (alertmanager-account config)
+  (match-record config <alertmanager-configuration>
+    (user group)
+    (list (user-group
+           (name group)
+           (system? #t))
+          (user-account
+           (name user)
+           (group group)
+           (system? #t)
+           (comment "Alertmanager user")
+           (home-directory "/var/lib/alertmanager")
+           (shell (file-append shadow "/sbin/nologin"))))))
+
+(define alertmanager-service-type
+  (service-type
+   (name 'alertmanager)
+   (description
+    "Run @command{alertmanager} to scrape targets for mertrics and provide the
+web interface.")
+   (extensions
+    (list (service-extension shepherd-root-service-type
+                             (compose list alertmanager-shepherd-service))
+          (service-extension account-service-type
+                             alertmanager-account)))
+   (default-value (alertmanager-configuration))))
+
 
 ;;;
 ;;; Zabbix server
diff --git a/gnu/tests/monitoring.scm b/gnu/tests/monitoring.scm
index e8c0847229..b77b654abc 100644
--- a/gnu/tests/monitoring.scm
+++ b/gnu/tests/monitoring.scm
@@ -33,6 +33,7 @@
   #:use-module (guix gexp)
   #:export (%test-prometheus
             %test-prometheus-node-exporter
+            %test-alertmanager
             %test-zabbix))
 
 
@@ -176,6 +177,76 @@
    (value (run-prometheus-node-exporter-server-test
            name %prometheus-node-exporter-os))))
 
+
+;;;
+;;; Alertmanager
+;;;
+
+(define* (run-alertmanager-test name test-os)
+  "Run tests in %TEST-OS, which has Alertmanager running."
+  (define os
+    (marionette-operating-system
+     test-os
+     #:imported-modules '((gnu services herd))))
+
+  (define vm
+    (virtual-machine
+     (operating-system os)
+     (port-forwardings '((8080 . 9093)))))
+
+  (define test
+    (with-imported-modules '((gnu build marionette))
+      #~(begin
+          (use-modules (srfi srfi-11)
+                       (srfi srfi-64)
+                       (gnu build marionette)
+                       (web client)
+                       (web response))
+
+          (define marionette
+            (make-marionette (list #$vm)))
+
+          (mkdir #$output)
+          (chdir #$output)
+
+          (test-begin #$name)
+
+          (test-assert "alertmanager running"
+            (marionette-eval
+             '(begin
+                (use-modules (gnu services herd))
+                (match (start-service 'alertmanager)
+                  (#f #f)
+                  (('service response-parts ...)
+                   (match (assq-ref response-parts 'running)
+                     ((pid) (number? pid))))))
+             marionette))
+
+          (test-equal "alertmanager healthy"
+            200
+            (begin
+              (wait-for-tcp-port 9090 marionette)
+              (let-values (((response text)
+                            (http-get "http://localhost:8080/-/healthy")))
+                (response-code response))))
+
+          (test-end)
+          (exit (= (test-runner-fail-count (test-runner-current)) 0)))))
+
+  (gexp->derivation (string-append name "-test") test))
+
+(define %alertmanager-test-os
+  (simple-operating-system
+   (service dhcp-client-service-type)
+   (service alertmanager-service-type)))
+
+(define %test-alertmanager
+  (system-test
+   (name "alertmanager")
+   (description "Connect to a running Alertmanager service.")
+   (value (run-alertmanager-test name
+                               %alertmanager-test-os))))
+
 
 ;;;
 ;;; Zabbix
-- 
2.26.0