CluPilotCloud/app/Livewire/Admin/Hosts.php

78 lines
2.5 KiB
PHP

<?php
namespace App\Livewire\Admin;
use App\Models\Datacenter;
use App\Models\Host;
use App\Services\Wireguard\PeerSnapshot;
use App\Services\Wireguard\WireguardHub;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Url;
use Livewire\Component;
#[Layout('layouts.admin')]
class Hosts extends Component
{
#[Url(as: 'q')]
public string $search = '';
#[Url]
public string $datacenter = '';
#[Url]
public string $status = '';
public function updated(): void
{
// no-op; keeps the query string in sync as filters change
}
public function clearFilters(): void
{
$this->reset('search', 'datacenter', 'status');
}
public function render()
{
$hosts = Host::query()
->withCount('instances')
->when($this->search !== '', function ($q) {
$term = '%'.$this->search.'%';
$q->where(fn ($w) => $w->where('name', 'like', $term)->orWhere('public_ip', 'like', $term));
})
->when($this->datacenter !== '', fn ($q) => $q->where('datacenter', $this->datacenter))
->when($this->status !== '', fn ($q) => $q->where('status', $this->status))
->orderBy('datacenter')->orderBy('name')
->get();
return view('livewire.admin.hosts', [
'hosts' => $hosts,
'datacenters' => Datacenter::query()->orderBy('name')->get(),
'statuses' => ['pending', 'onboarding', 'active', 'error', 'disabled'],
'total' => Host::query()->count(),
...$this->vpnPeerState(),
]);
}
/**
* One hub call for the whole list, not one per host — peers() already
* returns every peer keyed by public key, so a row just looks itself up.
*
* The hub can be down, or (dev/self-hosted) the `vpn` compose profile not
* running at all; either way this must not turn into a page-breaking
* exception. $hubReachable false is what tells vpnState() to answer
* "unknown" instead of guessing "silent" from an empty map — a wrong green
* (or a wrong amber) is worse than an honest blank.
*
* @return array{vpnPeersByKey: array<string, PeerSnapshot>, vpnHubReachable: bool}
*/
private function vpnPeerState(): array
{
try {
return ['vpnPeersByKey' => app(WireguardHub::class)->peers(), 'vpnHubReachable' => true];
} catch (\Throwable) {
return ['vpnPeersByKey' => [], 'vpnHubReachable' => false];
}
}
}