OpenNIT

Quelltext des aktuellen Standes

Fassung 1.1.1

ZabbixHostTemplateTest.php

7 KB
<?php

declare(strict_types=1);

use OpenNIT\Monitoring\ZabbixHostTemplate;

/**
 * Deckt die Vorlage ab, mit der Zabbix die Kennzahlen der Instanz abfragt.
 *
 * Eine Vorlage, die Zabbix beim Import abweist, ist schlimmer als keine – der
 * Aufbau wird deshalb hier festgehalten: die Fassung, das eine Haupt-Element,
 * die Bindung der abhängigen Elemente daran und das Dashboard mit den fünf
 * Ticketzahlen.
 */
return static function (): void {

    $yaml = static fn(string $url = 'https://doku.example.test'): string
        => ZabbixHostTemplate::yaml($url);

    test('Der Kopf nennt eine Fassung, die jeder neuere Stand einspielt', function () use ($yaml) {
        $text = $yaml();
        assertTrue(str_contains($text, 'zabbix_export:'), 'Der Wurzelknoten fehlt');
        // Zabbix spielt eine ältere Fassung in einen neueren Stand ein,
        // umgekehrt nicht – deshalb die niedrigste noch gepflegte.
        assertTrue(str_contains($text, "  version: '6.0'"), 'Die Fassung fehlt oder ist zu hoch');
        assertTrue(str_contains($text, '  templates:'), 'Der Abschnitt der Vorlagen fehlt');
        assertTrue(str_contains($text, "      template: 'OpenNIT by HTTP'"), 'Der Name der Vorlage fehlt');
    });

    test('Ein einziges Element holt die Daten, alle übrigen hängen daran', function () use ($yaml) {
        $text = $yaml();

        assertTrue(str_contains($text, '          type: HTTP_AGENT'), 'Das abrufende Element fehlt');
        assertTrue(str_contains($text, '          key: opennit.metrics'), 'Der Schlüssel des Haupt-Elements fehlt');
        assertTrue(
            str_contains($text, "          url: '{\$OPENNIT.URL}/api/ex/monitoring/metrics'"),
            'Die Adresse des Endpunkts fehlt'
        );
        assertTrue(
            str_contains($text, "              value: 'Bearer {\$OPENNIT.TOKEN}'"),
            'Die Kopfzeile mit dem Token fehlt'
        );

        // Jedes abhängige Element nennt dasselbe Haupt-Element.
        $abhaengig = substr_count($text, '          type: DEPENDENT');
        $bindungen = substr_count($text, '            key: opennit.metrics');
        assertTrue($abhaengig > 20, 'Zu wenige abhängige Elemente: ' . $abhaengig);
        assertSame($abhaengig, $bindungen, 'Nicht jedes abhängige Element hängt am Haupt-Element');
    });

    test('Die fünf Ticketzahlen sind vorhanden und stehen auf dem Dashboard', function () use ($yaml) {
        $text = $yaml();

        foreach (['new', 'open', 'waiting', 'solved', 'closed'] as $zustand) {
            assertTrue(
                str_contains($text, '          key: opennit.tickets.' . $zustand),
                'Das Element für „' . $zustand . '" fehlt'
            );
            assertTrue(
                str_contains($text, "                        key: 'opennit.tickets." . $zustand . "'"),
                'Die Kachel für „' . $zustand . '" fehlt auf dem Dashboard'
            );
        }

        assertTrue(str_contains($text, '      dashboards:'), 'Der Abschnitt der Dashboards fehlt');
        assertTrue(str_contains($text, "          name: 'OpenNIT – Tickets'"), 'Das Dashboard fehlt');
    });

    test('Die Kacheln liegen nebeneinander und passen ins Raster', function () use ($yaml) {
        $text = $yaml();

        // Zabbix rechnet mit 24 Spalten; sechs Kacheln zu vier Spalten füllen sie genau.
        preg_match_all("/^                  x: '(\\d+)'$/m", $text, $treffer);
        $spalten = array_map('intval', $treffer[1]);

        assertSame([0, 4, 8, 12, 16, 20], $spalten, 'Die Kacheln liegen nicht nebeneinander');
        assertSame(6, substr_count($text, "                  width: '4'"), 'Nicht jede Kachel ist vier Spalten breit');
    });

    test('Jeder Auslöser nennt ein Element, das es gibt', function () use ($yaml) {
        $text = $yaml();

        preg_match_all("/\\/OpenNIT by HTTP\\/([a-z0-9._\\[\\]{}#]+)[,)]/", $text, $treffer);
        assertTrue($treffer[1] !== [], 'Kein Auslöser gefunden');

        foreach (array_unique($treffer[1]) as $key) {
            // Element-Prototypen der Erkennung tragen eine Marke im Schlüssel.
            $gesucht = str_contains($key, '{#')
                ? "              key: '" . $key . "'"
                : '          key: ' . $key;
            assertTrue(
                str_contains($text, $gesucht),
                'Der Auslöser verweist auf ein Element, das die Vorlage nicht anlegt: ' . $key
            );
        }
    });

    test('Die Adresse der Instanz steht im Makro, der Token nicht in der Datei', function () use ($yaml) {
        $text = $yaml('https://doku.example.test');

        assertTrue(
            str_contains($text, "        - macro: '{\$OPENNIT.URL}'")
            && str_contains($text, "          value: 'https://doku.example.test'"),
            'Die Adresse fehlt im Makro'
        );
        // Der Token wird am Host gesetzt; eine Vorlage ohne Geheimnis lässt sich
        // weitergeben, ohne dass jemand nachdenken muss.
        assertTrue(
            str_contains($text, "        - macro: '{\$OPENNIT.TOKEN}'\n          value: ''"),
            'Das Token-Makro ist nicht leer'
        );
    });

    test('Die Erkennung der geplanten Aufgaben ist vollständig', function () use ($yaml) {
        $text = $yaml();

        assertTrue(str_contains($text, '      discovery_rules:'), 'Der Abschnitt der Erkennung fehlt');
        assertTrue(str_contains($text, '          key: opennit.tasks.discovery'), 'Die Regel fehlt');
        assertTrue(str_contains($text, "            - lld_macro: '{#TASK}'"), 'Die Marke der Aufgabe fehlt');
        assertTrue(str_contains($text, '          item_prototypes:'), 'Die Element-Prototypen fehlen');
        assertTrue(str_contains($text, '          trigger_prototypes:'), 'Der Auslöser-Prototyp fehlt');
    });

    test('Jede Kennung ist eindeutig', function () use ($yaml) {
        $text = $yaml();

        preg_match_all('/uuid: ([a-f0-9]{32})/', $text, $treffer);
        $kennungen = $treffer[1];

        assertTrue($kennungen !== [], 'Keine Kennung gefunden');
        assertSame(
            count($kennungen),
            count(array_unique($kennungen)),
            'Zwei Objekte tragen dieselbe Kennung – Zabbix weist den Import ab'
        );
    });

    test('Dieselbe Eingabe ergibt dieselben Kennungen', function () use ($yaml) {
        // Nur so aktualisiert ein erneuter Import die Vorlage, statt eine
        // zweite daneben anzulegen.
        preg_match_all('/uuid: ([a-f0-9]{32})/', $yaml(), $a);
        preg_match_all('/uuid: ([a-f0-9]{32})/', $yaml('https://andere.example.test'), $b);

        assertSame($a[1], $b[1], 'Die Kennungen hängen an der Adresse');
    });
};