Files
cosmoserver/files/server/server.php
2026-03-30 19:59:39 -07:00

159 lines
5.9 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
function h(string $s): string
{
return htmlspecialchars($s, ENT_QUOTES, 'UTF-8');
}
// Load API data
$raw_api_settings = file('/app/cosmostat_settings.yaml',
FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$api_settings = [];
foreach ($raw_api_settings as $line) {
if (isset($line[0]) && $line[0] === '#') { continue; }
$pos = strpos($line, ':');
if ($pos === false) { continue; }
$key = trim(substr($line, 0, $pos));
$value = trim(substr($line, $pos + 1));
if ($value === '') { $value = null; }
$api_settings[$key] = $value;
}
$api_bind_ip = trim($api_settings['api_bind_ip'] ?? '', "\"'");
$customApiPort = trim($api_settings['custom_api_port'] ?? '', "\"'");
$apiUrl = "http://$api_bind_ip:$customApiPort/client_details";
echo "<!-- ".$apiUrl . " -->";
$context = stream_context_create([
'http' => [
'timeout' => 5,
'header' => "User-Agent: PHP/" . PHP_VERSION . "\r\n"
]
]);
$json = @file_get_contents($apiUrl, false, $context);
if ($json === false) {
die('<p style="color:red;">Could not fetch data from the API.</p>');
}
$clients = json_decode($json, true);
if ($clients === null || !is_array($clients)) {
die('<p style="color:red;">Malformed JSON returned from the API.</p>');
}
// hostname get handler
$selectedId = $_GET['host'] ?? ''; // the value passed in ?host=
$selectedIdx = null;
foreach ($clients as $idx => $client) {
if (isset($client['short_id']) && $client['short_id'] === $selectedId) {
$selectedIdx = $idx;
break;
}
}
if ($selectedIdx === null) {
// No match fall back to the first client (or none)
$selectedIdx = 0;
$selectedId = $clients[$selectedIdx]['short_id'] ?? '';
}
$client = $clients[$selectedIdx] ?? null;
$properties = $client['client_properties'][0] ?? [];
$systemProperties = $properties['system_properties'] ?? [];
$systemComponents = $properties['system_components'] ?? [];
$selectedHost = $clients[$selectedIdx]['hostname'];
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Cosmostat - <?= h($selectedHost) ?></title>
<link rel="stylesheet" href="src/styles.css">
</head>
<body>
<div class="wrapper">
<!-- Sidebar -->
<nav class="sidebar">
<h3>Endpoints</h3>
<!-- The list will be populated by JavaScript -->
<ol id="endpointList"></ol>
</nav>
<!-- Main content -->
<div class="main">
<!-- Header Card -->
<div class="card">
<h2>Matt-Cloud Cosmostat Dashboard</h2>
<p>This dashboard shows the local Matt-Cloud system stats.</p>
<div class="help-link" id="helpToggle">API</div>
</div> <!-- / Header Card -->
<!-- Hidden API Card -->
<div id="helpText" class="card">
<strong>Component Desriptor</strong>
<p>To view the component descriptor, you may <br>
<code>curl -s https://<?= h($_SERVER['SERVER_NAME']) ?>/descriptor</code></p>
This will return the entire JSON descriptor variable.<br>
The endpoint agent uses this descriptor to build out its local System Object.<br>
The agent then reports back to the Cosmostat Server with all the data found in the descriptor.<br>
Full Source Code can be found at its <a target="_blank" rel="noopener noreferrer" href=https://gitea.matt-cloud.com/matt/cosmoserver>Gitea</a> page.
</div> <!-- / Header Card -->
<!-- summary card -->
<div class="card">
<?php if (!empty($systemProperties)): ?><h2>System Properties</h2>
<table><tr>
<td>
<ul class="system-list">
<?php foreach ($systemProperties as $prop): ?><li><?= h($prop['Property']) ?></li>
<?php endforeach; ?></ul>
</td><td>
<h2>Live System Metrics</h2>
<!-- Live content, javascript rendered -->
<div id="host_metrics" class="column">
Connecting...
</div> <!--/live content -->
</td>
</tr></table>
<?php endif; ?><br>
<!-- api help toggle -->
<div class="componentDetail-link" id="componentDetailToggle">Toggle Component Details</div>
</div> <!--/summary card -->
<!-- hidden detail card -->
<div id="componentDetailText" class="card">
<?php if (!empty($systemComponents)): ?><h2>Components</h2>
<!-- component bucket -->
<div class="components">
<?php foreach ($systemComponents as $comp): ?>
<!-- individual component -->
<div class="component">
<h3><?= h($comp['component_name']) ?></h3>
<ul class="info-list">
<?php foreach ($comp['info_strings'] as $info): ?><li><?= h($info) ?></li>
<?php endforeach; ?></ul>
</div> <!--/individual component -->
<?php endforeach; ?></div> <!--/component bucket -->
<?php endif; ?></div> <!--/hidden detail card -->
</div> <!-- /main -->
</div> <!-- /wrapper -->
<!-- Socket.IO client library -->
<script src="socket.io/socket.io.js"></script>
<!-- system metrics script -->
<script src="src/system_metrics.js"></script>
<!-- Panel Toggles -->
<script>
document.getElementById('helpToggle').addEventListener('click', function () {
const help = document.getElementById('helpText');
help.style.display = help.style.display === 'none' || help.style.display === '' ? 'block' : 'none';
});
document.getElementById('componentDetailToggle').addEventListener('click', function () {
const help = document.getElementById('componentDetailText');
help.style.display = help.style.display === 'none' || help.style.display === '' ? 'block' : 'none';
});
</script>
</body>
</html>