| 1 | ;;; GNU Guix --- Functional package management for GNU |
| 2 | ;;; Copyright © 2018 Gábor Boskovits <boskovits@gmail.com> |
| 3 | ;;; Copyright © 2018, 2019 Oleg Pykhalov <go.wigust@gmail.com> |
| 4 | ;;; |
| 5 | ;;; This file is part of GNU Guix. |
| 6 | ;;; |
| 7 | ;;; GNU Guix is free software; you can redistribute it and/or modify it |
| 8 | ;;; under the terms of the GNU General Public License as published by |
| 9 | ;;; the Free Software Foundation; either version 3 of the License, or (at |
| 10 | ;;; your option) any later version. |
| 11 | ;;; |
| 12 | ;;; GNU Guix is distributed in the hope that it will be useful, but |
| 13 | ;;; WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | ;;; GNU General Public License for more details. |
| 16 | ;;; |
| 17 | ;;; You should have received a copy of the GNU General Public License |
| 18 | ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. |
| 19 | |
| 20 | (define-module (gnu tests monitoring) |
| 21 | #:use-module (gnu packages databases) |
| 22 | #:use-module (gnu packages monitoring) |
| 23 | #:use-module (gnu packages php) |
| 24 | #:use-module (gnu services) |
| 25 | #:use-module (gnu services monitoring) |
| 26 | #:use-module (gnu services networking) |
| 27 | #:use-module (gnu services databases) |
| 28 | #:use-module (gnu services shepherd) |
| 29 | #:use-module (gnu services web) |
| 30 | #:use-module (gnu system vm) |
| 31 | #:use-module (gnu system) |
| 32 | #:use-module (gnu tests) |
| 33 | #:use-module (guix gexp) |
| 34 | #:export (%test-prometheus-node-exporter |
| 35 | %test-zabbix)) |
| 36 | |
| 37 | \f |
| 38 | ;;; |
| 39 | ;;; Prometheus Node Exporter |
| 40 | ;;; |
| 41 | |
| 42 | (define* (run-prometheus-node-exporter-server-test name test-os) |
| 43 | "Run tests in %PROMETHEUS-NODE-EXPORTER-OS, which has prometheus-node-exporter running." |
| 44 | (define os |
| 45 | (marionette-operating-system |
| 46 | test-os |
| 47 | #:imported-modules '((gnu services herd)))) |
| 48 | |
| 49 | (define vm |
| 50 | (virtual-machine |
| 51 | (operating-system os) |
| 52 | (port-forwardings '((8080 . 9100))))) |
| 53 | |
| 54 | (define test |
| 55 | (with-imported-modules '((gnu build marionette)) |
| 56 | #~(begin |
| 57 | (use-modules (srfi srfi-11) |
| 58 | (srfi srfi-64) |
| 59 | (gnu build marionette) |
| 60 | (web client) |
| 61 | (web response)) |
| 62 | |
| 63 | (define marionette |
| 64 | (make-marionette (list #$vm))) |
| 65 | |
| 66 | (test-runner-current (system-test-runner #$output)) |
| 67 | (test-begin #$name) |
| 68 | |
| 69 | (test-assert "prometheus-node-exporter running" |
| 70 | (marionette-eval |
| 71 | '(begin |
| 72 | (use-modules (gnu services herd)) |
| 73 | (match (start-service 'prometheus-node-exporter) |
| 74 | (#f #f) |
| 75 | (('service response-parts ...) |
| 76 | (match (assq-ref response-parts 'running) |
| 77 | ((pid) (number? pid)))))) |
| 78 | marionette)) |
| 79 | |
| 80 | (test-equal "http-get" |
| 81 | 200 |
| 82 | (begin |
| 83 | (wait-for-tcp-port 9100 marionette) |
| 84 | (let-values (((response text) |
| 85 | (http-get "http://localhost:8080"))) |
| 86 | (response-code response)))) |
| 87 | |
| 88 | (test-end)))) |
| 89 | |
| 90 | (gexp->derivation (string-append name "-test") test)) |
| 91 | |
| 92 | (define %prometheus-node-exporter-os |
| 93 | (simple-operating-system |
| 94 | (service dhcp-client-service-type) |
| 95 | (service prometheus-node-exporter-service-type |
| 96 | (prometheus-node-exporter-configuration)))) |
| 97 | |
| 98 | (define %test-prometheus-node-exporter |
| 99 | (system-test |
| 100 | (name "prometheus-node-exporter") |
| 101 | (description "Connect to a running prometheus-node-exporter server.") |
| 102 | (value (run-prometheus-node-exporter-server-test |
| 103 | name %prometheus-node-exporter-os)))) |
| 104 | |
| 105 | \f |
| 106 | ;;; |
| 107 | ;;; Zabbix |
| 108 | ;;; |
| 109 | |
| 110 | (define %psql-user-create-zabbix |
| 111 | "\ |
| 112 | sudo -u postgres psql <<< \"create user zabbix password 'zabbix';\" |
| 113 | ") |
| 114 | |
| 115 | (define %psql-db-zabbix-create-script |
| 116 | "\ |
| 117 | sudo -u postgres psql --no-align <<< \\\\du |
| 118 | ") |
| 119 | |
| 120 | (define %psql-db-create-zabbix |
| 121 | "\ |
| 122 | sudo -u postgres createdb -O zabbix -E Unicode -T template0 zabbix |
| 123 | ") |
| 124 | |
| 125 | (define %psql-db-import-zabbix |
| 126 | #~(format #f "\ |
| 127 | cat ~a | sudo -u zabbix psql zabbix; |
| 128 | cat ~a | sudo -u zabbix psql zabbix; |
| 129 | cat ~a | sudo -u zabbix psql zabbix; |
| 130 | " |
| 131 | (string-append #$zabbix-server:schema |
| 132 | "/database/postgresql/schema.sql") |
| 133 | (string-append #$zabbix-server:schema |
| 134 | "/database/postgresql/images.sql") |
| 135 | (string-append #$zabbix-server:schema |
| 136 | "/database/postgresql/data.sql"))) |
| 137 | |
| 138 | (define* (run-zabbix-server-test name test-os) |
| 139 | "Run tests in %ZABBIX-OS, which has zabbix running." |
| 140 | (define os |
| 141 | (marionette-operating-system |
| 142 | test-os |
| 143 | #:imported-modules '((gnu services herd)))) |
| 144 | |
| 145 | (define vm |
| 146 | (virtual-machine |
| 147 | (operating-system os) |
| 148 | (port-forwardings '((8080 . 80))) |
| 149 | (memory-size 1024))) |
| 150 | |
| 151 | (define test |
| 152 | (with-imported-modules '((gnu build marionette)) |
| 153 | #~(begin |
| 154 | (use-modules (srfi srfi-11) |
| 155 | (srfi srfi-64) |
| 156 | (gnu build marionette) |
| 157 | (web client) |
| 158 | (web response) |
| 159 | (ice-9 popen) |
| 160 | (ice-9 rdelim)) |
| 161 | |
| 162 | (define marionette |
| 163 | (make-marionette (list #$vm))) |
| 164 | |
| 165 | (test-runner-current (system-test-runner #$output)) |
| 166 | (test-begin #$name) |
| 167 | |
| 168 | ;; XXX: Shepherd reads the config file *before* binding its control |
| 169 | ;; socket, so /var/run/shepherd/socket might not exist yet when the |
| 170 | ;; 'marionette' service is started. |
| 171 | (test-assert "shepherd socket ready" |
| 172 | (marionette-eval |
| 173 | `(begin |
| 174 | (use-modules (gnu services herd)) |
| 175 | (let loop ((i 10)) |
| 176 | (cond ((file-exists? (%shepherd-socket-file)) |
| 177 | #t) |
| 178 | ((> i 0) |
| 179 | (sleep 1) |
| 180 | (loop (- i 1))) |
| 181 | (else |
| 182 | 'failure)))) |
| 183 | marionette)) |
| 184 | |
| 185 | (test-assert "postgres service running" |
| 186 | (marionette-eval |
| 187 | '(begin |
| 188 | (use-modules (gnu services herd)) |
| 189 | (start-service 'postgres)) |
| 190 | marionette)) |
| 191 | |
| 192 | ;; Add /run/setuid-programs to $PATH so that the scripts passed to |
| 193 | ;; 'system' can find 'sudo'. |
| 194 | (marionette-eval |
| 195 | '(setenv "PATH" |
| 196 | "/run/setuid-programs:/run/current-system/profile/bin") |
| 197 | marionette) |
| 198 | |
| 199 | (test-eq "postgres create zabbix user" |
| 200 | 0 |
| 201 | (marionette-eval '(begin (system #$%psql-user-create-zabbix)) |
| 202 | marionette)) |
| 203 | |
| 204 | (test-equal "postgres find zabbix user" |
| 205 | "List of roles |
| 206 | Role name|Attributes|Member of |
| 207 | postgres|Superuser, Create role, Create DB, Replication, Bypass RLS|{} |
| 208 | zabbix||{} |
| 209 | " |
| 210 | (marionette-eval |
| 211 | '(begin (let* ((port (open-pipe #$%psql-db-zabbix-create-script |
| 212 | OPEN_READ)) |
| 213 | (output (read-string port)) |
| 214 | (status (close-pipe port))) |
| 215 | output)) |
| 216 | marionette)) |
| 217 | |
| 218 | (test-eq "postgres create zabbix db" |
| 219 | 0 |
| 220 | (marionette-eval '(begin (system #$%psql-db-create-zabbix)) |
| 221 | marionette)) |
| 222 | |
| 223 | (test-eq "postgres import zabbix db" |
| 224 | 0 |
| 225 | (marionette-eval '(begin (system #$%psql-db-import-zabbix)) |
| 226 | marionette)) |
| 227 | |
| 228 | ;; Wait for zabbix-server to be up and running. |
| 229 | (test-assert "zabbix-server running" |
| 230 | (marionette-eval |
| 231 | '(begin |
| 232 | (use-modules (gnu services herd)) |
| 233 | (start-service 'zabbix-server)) |
| 234 | marionette)) |
| 235 | |
| 236 | ;; Make sure the PID file is created. |
| 237 | (test-assert "zabbix-server PID file" |
| 238 | (marionette-eval |
| 239 | '(file-exists? "/var/run/zabbix/zabbix_server.pid") |
| 240 | marionette)) |
| 241 | |
| 242 | ;; Wait for zabbix-agent to be up and running. |
| 243 | (test-assert "zabbix-agent running" |
| 244 | (marionette-eval |
| 245 | '(begin |
| 246 | (use-modules (gnu services herd)) |
| 247 | (start-service 'zabbix-agent)) |
| 248 | marionette)) |
| 249 | |
| 250 | ;; Make sure the PID file is created. |
| 251 | (test-assert "zabbix-agent PID file" |
| 252 | (marionette-eval |
| 253 | '(file-exists? "/var/run/zabbix/zabbix_agent.pid") |
| 254 | marionette)) |
| 255 | |
| 256 | ;; Wait for php-fpm to be up and running. |
| 257 | (test-assert "php-fpm running" |
| 258 | (marionette-eval |
| 259 | '(begin |
| 260 | (use-modules (gnu services herd)) |
| 261 | (start-service 'php-fpm)) |
| 262 | marionette)) |
| 263 | |
| 264 | ;; Wait for nginx to be up and running. |
| 265 | (test-assert "nginx running" |
| 266 | (marionette-eval |
| 267 | '(begin |
| 268 | (use-modules (gnu services herd)) |
| 269 | (start-service 'nginx)) |
| 270 | marionette)) |
| 271 | |
| 272 | ;; Make sure the PID file is created. |
| 273 | (test-assert "nginx PID file" |
| 274 | (marionette-eval |
| 275 | '(file-exists? "/var/run/nginx/pid") |
| 276 | marionette)) |
| 277 | |
| 278 | ;; Make sure we can access pages that correspond to our Zabbix instance. |
| 279 | (letrec-syntax ((test-url |
| 280 | (syntax-rules () |
| 281 | ((_ path code) |
| 282 | (test-equal (string-append "GET " path) |
| 283 | code |
| 284 | (let-values (((response body) |
| 285 | (http-get (string-append |
| 286 | "http://localhost:8080" |
| 287 | path)))) |
| 288 | (response-code response)))) |
| 289 | ((_ path) |
| 290 | (test-url path 200))))) |
| 291 | (test-url "/") |
| 292 | (test-url "/does-not-exist" 404)) |
| 293 | |
| 294 | (test-end)))) |
| 295 | |
| 296 | (gexp->derivation (string-append name "-test") test)) |
| 297 | |
| 298 | (define %zabbix-os |
| 299 | ;; Return operating system under test. |
| 300 | (let ((base-os |
| 301 | (simple-operating-system |
| 302 | (service dhcp-client-service-type) |
| 303 | (service postgresql-service-type |
| 304 | (postgresql-configuration |
| 305 | (postgresql postgresql))) |
| 306 | (service zabbix-front-end-service-type |
| 307 | (zabbix-front-end-configuration |
| 308 | (db-password "zabbix"))) |
| 309 | |
| 310 | (service php-fpm-service-type |
| 311 | (php-fpm-configuration |
| 312 | (timezone "Europe/Paris"))) |
| 313 | |
| 314 | (service zabbix-server-service-type |
| 315 | (zabbix-server-configuration |
| 316 | (db-password "zabbix") |
| 317 | (log-type "console"))) |
| 318 | |
| 319 | (service zabbix-agent-service-type)))) |
| 320 | (operating-system |
| 321 | (inherit base-os) |
| 322 | (packages (cons* postgresql (operating-system-packages base-os)))))) |
| 323 | |
| 324 | (define %test-zabbix |
| 325 | (system-test |
| 326 | (name "zabbix") |
| 327 | (description "Connect to a running Zabbix") |
| 328 | (value (run-zabbix-server-test name %zabbix-os)))) |