Skip to content
Snippets Groups Projects
amcli.php 5.50 KiB
#!/usr/bin/env php
<?php

chdir(__DIR__);
$FLAG_DEBUG = 0;
$VERSION = "0.0.1";

// ---MARK---INCLUDE-CHECKS---START---
if (!file_exists("include_checks.php")) {
    echo "ERROR: File 'include_checks.php' does not exist yet..\n";
    echo "Run the ../installer.php first!\n";
    exit(1);
}

if (!include "include_checks.php") {
    echo "ERROR: Include of generated 'include_checks.php' failed.\n";
    echo "Check its generation by installer or run the installer again.\n";
    exit(2);
}
// ---MARK---INCLUDE-CHECKS---END


// --------------------------------------------------------------------
//
// FUNCTIONS
//
// --------------------------------------------------------------------


/**
 * Call $oMonitor-><METHODNAME> with 1 or 2 params.
 * This function was introduced to shorten the code.
 * 
 * @param string $sMethod  method name of appmonitor class
 * @param mixed  $value
 * @param mixed  $value2
 * @return void
 */
function _set(string $sMethod, mixed $value = null, mixed $value2 = null)
{
    global $oMonitor;
    if (!isset($value)) {
        _wd("SKIP \$oMonitor->$sMethod(<no_value>)");

    } else {
        if (!isset($value2)) {
            _wd("calling \$oMonitor->$sMethod('$value')");
            $oMonitor->$sMethod($value);
        } else {
            _wd("calling \$oMonitor->$sMethod('$value', '$value2')");
            $oMonitor->$sMethod($value, $value2);
        }
    }
}

/**
 * Write debug output if FLAG_DEBUG is true (use -v or --verbose on command line)
 * @param string $s  message to show; a prefix "DEBUG:" will be added in front
 * @return void
 */
function _wd($s): void
{
    global $FLAG_DEBUG;
    if ($FLAG_DEBUG) {
        // echo "DEBUG: $s\n";
        fwrite(STDERR, "DEBUG: $s\n");
    }
}

/**
 * Show help text
 * @return void
 */
function _showHelp(): void
{
    global $VERSION;
    $_self = basename(__FILE__);
    echo "IML Appmonitor as CLI client $VERSION

This client performs appmonitor checks and puts the results as JSON to stdout.
You can use the compiled binary on non PHP systems.
(c) 2025 Institute for Medical education * University of Bern

    !!! This tool is in alpha stadium !!!


SYNTAX: $_self [OPTIONS]

OPTIONS:
    -h, --help      Print this help and exit
    -i, --ini       Set an INI File to parse
    -l, --list      list available checks and exit; --ini will be ignored
    -v, --verbose   Verbose output
    -V, --version   Show version and exit

";
}

// --------------------------------------------------------------------
//
// MAIN
//
// --------------------------------------------------------------------

// put params to $ARGS
if ($argc > 1) {
    parse_str(implode('&', array_slice($argv, 1)), $ARGS);
}

// check params

if (isset($ARGS['-v']) || isset($ARGS['--verbose'])) {
    $FLAG_DEBUG = 1;
}
_wd("CLI ARGS: " . print_r($ARGS ?? [], 1));

// show version
if (isset($ARGS['-V']) || isset($ARGS['--version'])) {
    _wd("Showing version");
    echo "$VERSION\n";
    exit(0);
}

// show help
if (isset($ARGS['-h']) || isset($ARGS['--help'])) {
    _wd("Showing help");
    _showHelp();
    exit(0);
}

// ----------------------------------------------------------------------

_wd("Initializing appmonitor class");

$oMonitor = new appmonitor();

// show builtin checks
if (isset($ARGS['-l']) || isset($ARGS['--list'])) {
    echo implode("\n", $oMonitor->listChecks());
    exit(0);
}


$inifile = $ARGS["--ini"] ?? ($ARGS["-i"] ?? "simple.ini");
_wd("Using ini file '$inifile'.");

if (!file_exists($inifile)) {
    echo "ERROR: INI File '$inifile' does not exist.\n";
    exit(1);
}

$aIni = parse_ini_file($inifile, true);
if (!is_array($aIni)) {
    echo "ERROR: INI File '$inifile' could not be parsed.\n";
    exit(1);
}

_wd("Parsed INI data: " . print_r($aIni, 1));


// ----------------------------------------------------------------------

// set metadata
_set("setHost", $aIni['meta']['host'] ?? null);
_set("setWebsite", $aIni['meta']['website'] ?? null);
_set("setTtl", $aIni['meta']['ttl'] ?? null);

foreach ($aIni['notification']['email'] ?? [] as $sValue) {
    _set("addEmail", $sValue);
}
foreach ($aIni['notification']['slack'] ?? [] as $sValue) {
    $sChannel = preg_filter('/,.*/', '', $sValue);
    $sWebhook = preg_filter('/^.*,/', '', $sValue);

    _set("addSlackWebhook", $sChannel, $sWebhook);
}

// loop over checks
$aChecks = $aIni;
unset($aChecks["meta"]);
unset($aChecks["notification"]);

foreach ($aChecks as $sKey => $aCheck) {
    $aChecks[$sKey]['name'] = $aCheck['name'] ?? $sKey;
    if ($aCheck['params']) {
        $aArray = json_decode($aCheck['params'], 1);
        if (!is_array($aArray)) {
            echo "ERROR: key 'params' for check [$sKey] must be JSON.\n";
            echo "Value in $inifile: $aCheck[params]\n";
            exit(1);
        }
    }

    _wd("Execute Check '$sKey'");
    $oMonitor->addCheck([
        "name" => $aCheck['name'] ?? $sKey,
        "description" => $aCheck['description'],
        "check" => [
            "function" => $aCheck['function'],
            "params" => $aArray,
        ],
    ]);

    /*
    $oMonitor->addCheck(
        [
            "name" => "hello plugin",
            "description" => "Test a plugin ... plugins/checks/hello.php",
            "check" => [
                "function" => "Hello",
                "params" => [
                    "message" => "Here I am",
                ],
            ],
        ]
    );
    */

}


// ----------------------------------------------------------------------
// send the response

_wd("Setting result");
$oMonitor->setResult();

_wd("Send response");
$oMonitor->render();