mirror of
https://github.com/coollabsio/coolify.git
synced 2026-06-13 19:09:50 +00:00
feat(ui): move sentinel to new tab (#9544)
This commit is contained in:
@@ -2,11 +2,15 @@
|
||||
|
||||
namespace App\Livewire\Server;
|
||||
|
||||
use App\Actions\Server\StartSentinel;
|
||||
use App\Models\Server;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Livewire\Component;
|
||||
|
||||
class Charts extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
|
||||
public Server $server;
|
||||
|
||||
public $chartId = 'server';
|
||||
@@ -28,6 +32,29 @@ class Charts extends Component
|
||||
}
|
||||
}
|
||||
|
||||
public function toggleMetrics(): void
|
||||
{
|
||||
try {
|
||||
$this->authorize('update', $this->server);
|
||||
$this->server->settings->is_metrics_enabled = ! $this->server->settings->is_metrics_enabled;
|
||||
$this->server->settings->save();
|
||||
$this->server->refresh();
|
||||
|
||||
if ($this->server->isMetricsEnabled()) {
|
||||
StartSentinel::run($this->server, true);
|
||||
$this->dispatch('success', 'Metrics enabled. Starting Sentinel.');
|
||||
$this->dispatch('refreshServerShow');
|
||||
$this->redirect(route('server.metrics', ['server_uuid' => $this->server->uuid]), navigate: true);
|
||||
} else {
|
||||
$this->server->restartSentinel();
|
||||
$this->dispatch('success', 'Metrics disabled. Restarting Sentinel.');
|
||||
$this->dispatch('refreshServerShow');
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function pollData()
|
||||
{
|
||||
if ($this->poll || $this->interval <= 10) {
|
||||
|
||||
@@ -15,8 +15,6 @@ class Sentinel extends Component
|
||||
|
||||
public Server $server;
|
||||
|
||||
public array $parameters = [];
|
||||
|
||||
public bool $isMetricsEnabled;
|
||||
|
||||
#[Validate(['required', 'string', 'max:500', 'regex:/\A[a-zA-Z0-9._\-+=\/]+\z/'])]
|
||||
@@ -51,15 +49,9 @@ class Sentinel extends Component
|
||||
];
|
||||
}
|
||||
|
||||
public function mount(string $server_uuid)
|
||||
public function mount()
|
||||
{
|
||||
try {
|
||||
$this->server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail();
|
||||
$this->parameters = get_route_parameters();
|
||||
$this->syncData();
|
||||
} catch (\Throwable) {
|
||||
return redirect()->route('server.index');
|
||||
}
|
||||
$this->syncData();
|
||||
}
|
||||
|
||||
public function syncData(bool $toModel = false)
|
||||
@@ -112,27 +104,29 @@ class Sentinel extends Component
|
||||
}
|
||||
}
|
||||
|
||||
public function updatedIsSentinelEnabled($value)
|
||||
public function toggleSentinel(): void
|
||||
{
|
||||
try {
|
||||
$this->authorize('manageSentinel', $this->server);
|
||||
if ($value === true) {
|
||||
if (! $this->isSentinelEnabled) {
|
||||
if ($this->server->isBuildServer()) {
|
||||
$this->isSentinelEnabled = false;
|
||||
$this->dispatch('error', 'Sentinel cannot be enabled on build servers.');
|
||||
|
||||
return;
|
||||
}
|
||||
$this->isSentinelEnabled = true;
|
||||
$customImage = isDev() ? $this->sentinelCustomDockerImage : null;
|
||||
StartSentinel::run($this->server, true, null, $customImage);
|
||||
} else {
|
||||
$this->isSentinelEnabled = false;
|
||||
$this->isMetricsEnabled = false;
|
||||
$this->isSentinelDebugEnabled = false;
|
||||
StopSentinel::dispatch($this->server);
|
||||
}
|
||||
$this->submit();
|
||||
$this->dispatch('refreshServerShow');
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Server\Sentinel;
|
||||
|
||||
use App\Models\Server;
|
||||
use Illuminate\View\View;
|
||||
use Livewire\Component;
|
||||
|
||||
class Logs extends Component
|
||||
{
|
||||
public ?Server $server = null;
|
||||
|
||||
public array $parameters = [];
|
||||
|
||||
public function mount(): void
|
||||
{
|
||||
$this->parameters = get_route_parameters();
|
||||
try {
|
||||
$this->server = Server::ownedByCurrentTeam()->whereUuid(request()->server_uuid)->firstOrFail();
|
||||
} catch (\Throwable $e) {
|
||||
handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function render(): View
|
||||
{
|
||||
return view('livewire.server.sentinel.logs');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Server\Sentinel;
|
||||
|
||||
use App\Models\Server;
|
||||
use Illuminate\View\View;
|
||||
use Livewire\Component;
|
||||
|
||||
class Show extends Component
|
||||
{
|
||||
public ?Server $server = null;
|
||||
|
||||
public array $parameters = [];
|
||||
|
||||
public function mount(): void
|
||||
{
|
||||
$this->parameters = get_route_parameters();
|
||||
try {
|
||||
$this->server = Server::ownedByCurrentTeam()->whereUuid(request()->server_uuid)->firstOrFail();
|
||||
} catch (\Throwable $e) {
|
||||
handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function render(): View
|
||||
{
|
||||
return view('livewire.server.sentinel.show');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<div class="sub-menu-wrapper">
|
||||
<a class="{{ request()->routeIs('server.sentinel') ? 'sub-menu-item menu-item-active' : 'sub-menu-item' }}" {{ wireNavigate() }}
|
||||
href="{{ route('server.sentinel', $parameters) }}">
|
||||
<span class="menu-item-label">Configuration</span>
|
||||
</a>
|
||||
<a class="{{ request()->routeIs('server.sentinel.logs') ? 'sub-menu-item menu-item-active' : 'sub-menu-item' }}" {{ wireNavigate() }}
|
||||
href="{{ route('server.sentinel.logs', $parameters) }}">
|
||||
<span class="menu-item-label">Logs</span>
|
||||
</a>
|
||||
</div>
|
||||
@@ -6,11 +6,6 @@
|
||||
href="{{ route('server.advanced', ['server_uuid' => $server->uuid]) }}"><span class="menu-item-label">Advanced</span>
|
||||
</a>
|
||||
@endif
|
||||
@if ($server->isFunctional() && !$server->isSwarm() && !$server->isBuildServer())
|
||||
<a class="sub-menu-item {{ $activeMenu === 'sentinel' ? 'menu-item-active' : '' }}" {{ wireNavigate() }}
|
||||
href="{{ route('server.sentinel', ['server_uuid' => $server->uuid]) }}"><span class="menu-item-label">Sentinel</span>
|
||||
</a>
|
||||
@endif
|
||||
<a class="sub-menu-item {{ $activeMenu === 'private-key' ? 'menu-item-active' : '' }}" {{ wireNavigate() }}
|
||||
href="{{ route('server.private-key', ['server_uuid' => $server->uuid]) }}"><span class="menu-item-label">Private Key</span>
|
||||
</a>
|
||||
@@ -37,7 +32,7 @@
|
||||
<a class="sub-menu-item {{ $activeMenu === 'log-drains' ? 'menu-item-active' : '' }}" {{ wireNavigate() }}
|
||||
href="{{ route('server.log-drains', ['server_uuid' => $server->uuid]) }}"><span class="menu-item-label">Log Drains</span></a>
|
||||
<a class="sub-menu-item {{ $activeMenu === 'metrics' ? 'menu-item-active' : '' }}" {{ wireNavigate() }}
|
||||
href="{{ route('server.charts', ['server_uuid' => $server->uuid]) }}"><span class="menu-item-label">Metrics</span></a>
|
||||
href="{{ route('server.metrics', ['server_uuid' => $server->uuid]) }}"><span class="menu-item-label">Metrics</span></a>
|
||||
@endif
|
||||
@if (!$server->isBuildServer() && !$server->settings->is_cloudflare_tunnel)
|
||||
<a class="sub-menu-item {{ $activeMenu === 'swarm' ? 'menu-item-active' : '' }}" {{ wireNavigate() }}
|
||||
|
||||
@@ -5,13 +5,19 @@
|
||||
<div class="pb-4">Basic metrics for your application container.</div>
|
||||
<div>
|
||||
@if ($resource->getMorphClass() === 'App\Models\Application' && $resource->build_pack === 'dockercompose')
|
||||
<div class="alert alert-warning">Metrics are not available for Docker Compose applications yet!</div>
|
||||
<x-callout type="warning" title="Not Available">
|
||||
Metrics are not available for Docker Compose applications yet!
|
||||
</x-callout>
|
||||
@elseif(!$resource->destination->server->isMetricsEnabled())
|
||||
<div class="alert alert-warning pb-1">Metrics are only available for servers with Sentinel & Metrics enabled!</div>
|
||||
<div>Go to <a class="underline dark:text-white" href="{{ route('server.show', $resource->destination->server->uuid) }}/sentinel" {{ wireNavigate() }}>Server settings</a> to enable it.</div>
|
||||
<x-callout type="info" title="Metrics Not Enabled">
|
||||
Metrics are only available for servers with Sentinel & Metrics enabled.
|
||||
Go to <a class="underline font-semibold" href="{{ route('server.metrics', ['server_uuid' => $resource->destination->server->uuid]) }}" {{ wireNavigate() }}>Server Metrics</a> to enable it.
|
||||
</x-callout>
|
||||
@else
|
||||
@if (!str($resource->status)->contains('running'))
|
||||
<div class="alert alert-warning">Metrics are only available when the application container is running!</div>
|
||||
<x-callout type="warning" title="Container Not Running">
|
||||
Metrics are only available when the application container is running!
|
||||
</x-callout>
|
||||
@else
|
||||
<div>
|
||||
<x-forms.select label="Interval" wire:change="setInterval" id="interval">
|
||||
|
||||
@@ -6,7 +6,18 @@
|
||||
<div class="flex flex-col h-full gap-8 sm:flex-row">
|
||||
<x-server.sidebar :server="$server" activeMenu="metrics" />
|
||||
<div class="w-full">
|
||||
<h2>Metrics</h2>
|
||||
<div class="flex items-center gap-2">
|
||||
<h2>Metrics</h2>
|
||||
@if ($server->isMetricsEnabled())
|
||||
<x-forms.button canGate="update" :canResource="$server" wire:click='toggleMetrics'>
|
||||
Disable Metrics
|
||||
</x-forms.button>
|
||||
@elseif ($server->isSentinelEnabled())
|
||||
<x-forms.button canGate="update" :canResource="$server" isHighlighted wire:click='toggleMetrics'>
|
||||
Enable Metrics
|
||||
</x-forms.button>
|
||||
@endif
|
||||
</div>
|
||||
<div class="pb-4">Basic metrics for your server.</div>
|
||||
@if ($server->isMetricsEnabled())
|
||||
<div @if ($poll) wire:poll.5000ms='pollData' @endif x-init="$wire.loadData()">
|
||||
@@ -288,8 +299,16 @@
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
<div>Metrics are disabled for this server. Enable them in <a class="underline dark:text-white"
|
||||
href="{{ route('server.show', ['server_uuid' => $server->uuid]) }}/sentinel" {{ wireNavigate() }}>Sentinel</a> settings.</div>
|
||||
@if ($server->isSentinelEnabled())
|
||||
<x-callout type="info" title="Metrics Disabled">
|
||||
Metrics are disabled for this server. Click "Enable Metrics" above to start collecting metrics.
|
||||
</x-callout>
|
||||
@else
|
||||
<x-callout type="info" title="Sentinel Required">
|
||||
Metrics require Sentinel to be enabled.
|
||||
Please <a class="underline font-semibold" href="{{ route('server.sentinel', ['server_uuid' => $server->uuid]) }}" {{ wireNavigate() }}>enable Sentinel</a> first.
|
||||
</x-callout>
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -58,6 +58,17 @@
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
@if ($server->isSentinelEnabled())
|
||||
<div class="flex">
|
||||
<div class="flex items-center">
|
||||
@if ($server->isSentinelLive())
|
||||
<x-status.running status="Sentinel In Sync" noLoading />
|
||||
@else
|
||||
<x-status.stopped status="Sentinel Out of Sync" noLoading />
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
<div class="subtitle">{{ data_get($server, 'name') }}</div>
|
||||
<div class="navbar-main">
|
||||
@@ -70,7 +81,7 @@
|
||||
</a>
|
||||
|
||||
@if (!$server->isSwarmWorker() && !$server->settings->is_build_server)
|
||||
<a class="{{ request()->routeIs('server.proxy') ? 'dark:text-white' : '' }} flex items-center gap-1" href="{{ route('server.proxy', [
|
||||
<a class="{{ request()->routeIs('server.proxy') || request()->routeIs('server.proxy.*') ? 'dark:text-white' : '' }} flex items-center gap-1" href="{{ route('server.proxy', [
|
||||
'server_uuid' => data_get($server, 'uuid'),
|
||||
]) }}" {{ wireNavigate() }}>
|
||||
Proxy
|
||||
@@ -82,6 +93,19 @@
|
||||
@endif
|
||||
</a>
|
||||
@endif
|
||||
@if ($server->isFunctional() && !$server->isSwarm() && !$server->settings->is_build_server)
|
||||
<a class="{{ request()->routeIs('server.sentinel') || request()->routeIs('server.sentinel.*') ? 'dark:text-white' : '' }} flex items-center gap-1" href="{{ route('server.sentinel', [
|
||||
'server_uuid' => data_get($server, 'uuid'),
|
||||
]) }}" {{ wireNavigate() }}>
|
||||
Sentinel
|
||||
@if ($server->isSentinelEnabled() && !$server->isSentinelLive())
|
||||
<svg class="w-4 h-4 text-warning" viewBox="0 0 256 256" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="currentColor"
|
||||
d="M236.8 188.09L149.35 36.22a24.76 24.76 0 0 0-42.7 0L19.2 188.09a23.51 23.51 0 0 0 0 23.72A24.35 24.35 0 0 0 40.55 224h174.9a24.35 24.35 0 0 0 21.33-12.19a23.51 23.51 0 0 0 .02-23.72m-13.87 15.71a8.5 8.5 0 0 1-7.48 4.2H40.55a8.5 8.5 0 0 1-7.48-4.2a7.59 7.59 0 0 1 0-7.72l87.45-151.87a8.75 8.75 0 0 1 15 0l87.45 151.87a7.59 7.59 0 0 1-.04 7.72M120 144v-40a8 8 0 0 1 16 0v40a8 8 0 0 1-16 0m20 36a12 12 0 1 1-12-12a12 12 0 0 1 12 12" />
|
||||
</svg>
|
||||
@endif
|
||||
</a>
|
||||
@endif
|
||||
<a class="{{ request()->routeIs('server.resources') ? 'dark:text-white' : '' }}" href="{{ route('server.resources', [
|
||||
'server_uuid' => data_get($server, 'uuid'),
|
||||
]) }}" {{ wireNavigate() }}>
|
||||
|
||||
@@ -1,111 +1,73 @@
|
||||
<div>
|
||||
<x-slot:title>
|
||||
{{ data_get_str($server, 'name')->limit(10) }} > Sentinel | Coolify
|
||||
</x-slot>
|
||||
<livewire:server.navbar :server="$server" />
|
||||
<div class="flex flex-col h-full gap-8 sm:flex-row">
|
||||
<x-server.sidebar :server="$server" activeMenu="sentinel" />
|
||||
<div class="w-full">
|
||||
<form wire:submit.prevent='submit'>
|
||||
<div class="flex gap-2 items-center pb-2">
|
||||
<h2>Sentinel</h2>
|
||||
<x-helper helper="Sentinel reports your server's & container's health and collects metrics." />
|
||||
@if ($server->isSentinelEnabled())
|
||||
<div class="flex gap-2 items-center">
|
||||
@if ($server->isSentinelLive())
|
||||
<x-status.running status="In sync" noLoading title="{{ $sentinelUpdatedAt }}" />
|
||||
<x-forms.button type="submit" canGate="update" :canResource="$server">Save</x-forms.button>
|
||||
<x-forms.button wire:click='restartSentinel' canGate="update" :canResource="$server">Restart</x-forms.button>
|
||||
<x-slide-over fullScreen>
|
||||
<x-slot:title>Sentinel Logs</x-slot:title>
|
||||
<x-slot:content>
|
||||
<livewire:project.shared.get-logs :server="$server"
|
||||
container="coolify-sentinel" displayName="Sentinel" :collapsible="false"
|
||||
lazy />
|
||||
</x-slot:content>
|
||||
<x-forms.button @click="slideOverOpen=true">Logs</x-forms.button>
|
||||
</x-slide-over>
|
||||
@else
|
||||
<x-status.stopped status="Out of sync" noLoading
|
||||
title="{{ $sentinelUpdatedAt }}" />
|
||||
<x-forms.button type="submit" canGate="update" :canResource="$server">Save</x-forms.button>
|
||||
<x-forms.button wire:click='restartSentinel' canGate="update" :canResource="$server">Sync</x-forms.button>
|
||||
<x-slide-over fullScreen>
|
||||
<x-slot:title>Sentinel Logs</x-slot:title>
|
||||
<x-slot:content>
|
||||
<livewire:project.shared.get-logs :server="$server"
|
||||
container="coolify-sentinel" displayName="Sentinel" :collapsible="false"
|
||||
lazy />
|
||||
</x-slot:content>
|
||||
<x-forms.button @click="slideOverOpen=true">Logs</x-forms.button>
|
||||
</x-slide-over>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
<form wire:submit.prevent='submit'>
|
||||
<div class="flex gap-2 items-center pb-2">
|
||||
<h2>Sentinel</h2>
|
||||
<x-helper helper="Sentinel reports your server's & container's health and collects metrics." />
|
||||
@if (!$isSentinelEnabled)
|
||||
<x-forms.button canGate="update" :canResource="$server" isHighlighted wire:click="toggleSentinel">Enable Sentinel</x-forms.button>
|
||||
@else
|
||||
<div class="flex gap-2 items-center">
|
||||
<x-forms.button type="submit" canGate="update" :canResource="$server">Save</x-forms.button>
|
||||
<x-forms.button wire:click='restartSentinel' canGate="update" :canResource="$server">
|
||||
{{ $server->isSentinelLive() ? 'Restart' : 'Sync' }}
|
||||
</x-forms.button>
|
||||
<x-forms.button canGate="update" :canResource="$server" wire:click="toggleSentinel">Disable Sentinel</x-forms.button>
|
||||
</div>
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="w-full sm:w-96">
|
||||
<x-forms.checkbox canGate="update" :canResource="$server" wire:model.live="isSentinelEnabled"
|
||||
label="Enable Sentinel" />
|
||||
@if ($server->isSentinelEnabled())
|
||||
@if (isDev())
|
||||
<x-forms.checkbox canGate="update" :canResource="$server" id="isSentinelDebugEnabled"
|
||||
label="Enable Sentinel (with debug)" instantSave />
|
||||
@endif
|
||||
<x-forms.checkbox canGate="update" :canResource="$server" instantSave
|
||||
id="isMetricsEnabled" label="Enable Metrics" />
|
||||
@else
|
||||
@if (isDev())
|
||||
<x-forms.checkbox id="isSentinelDebugEnabled" label="Enable Sentinel (with debug)"
|
||||
disabled instantSave />
|
||||
@endif
|
||||
<x-forms.checkbox instantSave disabled id="isMetricsEnabled"
|
||||
label="Enable Metrics (enable Sentinel first)" />
|
||||
@endif
|
||||
</div>
|
||||
@if (isDev() && $server->isSentinelEnabled())
|
||||
<div class="pt-4" x-data="{
|
||||
customImage: localStorage.getItem('sentinel_custom_docker_image_{{ $server->uuid }}') || '',
|
||||
saveCustomImage() {
|
||||
localStorage.setItem('sentinel_custom_docker_image_{{ $server->uuid }}', this.customImage);
|
||||
$wire.set('sentinelCustomDockerImage', this.customImage);
|
||||
}
|
||||
}" x-init="$wire.set('sentinelCustomDockerImage', customImage)">
|
||||
<x-forms.input x-model="customImage" @input.debounce.500ms="saveCustomImage()"
|
||||
placeholder="e.g., sentinel:latest or myregistry/sentinel:dev"
|
||||
label="Custom Sentinel Docker Image (Dev Only)"
|
||||
helper="Override the default Sentinel Docker image for testing. Leave empty to use the default." />
|
||||
</div>
|
||||
@endif
|
||||
@if ($server->isSentinelEnabled())
|
||||
<div class="flex flex-wrap gap-2 sm:flex-nowrap items-end">
|
||||
<x-forms.input canGate="update" :canResource="$server" type="password" id="sentinelToken"
|
||||
label="Sentinel token" required helper="Token for Sentinel." />
|
||||
<x-forms.button canGate="update" :canResource="$server"
|
||||
wire:click="regenerateSentinelToken">Regenerate</x-forms.button>
|
||||
</div>
|
||||
|
||||
<x-forms.input canGate="update" :canResource="$server" id="sentinelCustomUrl" required
|
||||
label="Coolify URL"
|
||||
helper="URL to your Coolify instance. If it is empty that means you do not have a FQDN set for your Coolify instance." />
|
||||
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="flex flex-wrap gap-2 sm:flex-nowrap">
|
||||
<x-forms.input canGate="update" :canResource="$server" type="number" min="1"
|
||||
id="sentinelMetricsRefreshRateSeconds" label="Metrics rate (seconds)" required
|
||||
helper="Interval used for gathering metrics. Lower values result in more disk space usage." />
|
||||
<x-forms.input canGate="update" :canResource="$server" type="number" min="1"
|
||||
id="sentinelMetricsHistoryDays"
|
||||
label="Metrics history (days)" required
|
||||
helper="Number of days to retain metrics data for." />
|
||||
<x-forms.input canGate="update" :canResource="$server" type="number" min="10"
|
||||
id="sentinelPushIntervalSeconds" label="Push interval (seconds)" required
|
||||
helper="Interval at which metrics data is sent to the collector." />
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</form>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@if ($isSentinelEnabled && !$server->isSentinelLive())
|
||||
<x-callout type="warning" title="Out of Sync" class="mt-2">
|
||||
Sentinel is not in sync with your server. Click "Sync" to re-sync.
|
||||
</x-callout>
|
||||
@endif
|
||||
<div class="flex flex-col gap-2 pt-2">
|
||||
@if ($isSentinelEnabled && isDev())
|
||||
<div class="w-full sm:w-96">
|
||||
<x-forms.checkbox canGate="update" :canResource="$server" id="isSentinelDebugEnabled"
|
||||
label="Enable Sentinel (with debug)" instantSave />
|
||||
</div>
|
||||
@endif
|
||||
@if (isDev() && $server->isSentinelEnabled())
|
||||
<div class="pt-4" x-data="{
|
||||
customImage: localStorage.getItem('sentinel_custom_docker_image_{{ $server->uuid }}') || '',
|
||||
saveCustomImage() {
|
||||
localStorage.setItem('sentinel_custom_docker_image_{{ $server->uuid }}', this.customImage);
|
||||
$wire.set('sentinelCustomDockerImage', this.customImage);
|
||||
}
|
||||
}" x-init="$wire.set('sentinelCustomDockerImage', customImage)">
|
||||
<x-forms.input canGate="update" :canResource="$server" x-model="customImage"
|
||||
@input.debounce.500ms="saveCustomImage()"
|
||||
placeholder="e.g., sentinel:latest or myregistry/sentinel:dev"
|
||||
label="Custom Sentinel Docker Image (Dev Only)"
|
||||
helper="Override the default Sentinel Docker image for testing. Leave empty to use the default." />
|
||||
</div>
|
||||
@endif
|
||||
@if ($server->isSentinelEnabled())
|
||||
<div class="flex flex-wrap gap-2 sm:flex-nowrap items-end">
|
||||
<x-forms.input canGate="update" :canResource="$server" id="sentinelCustomUrl" required
|
||||
label="Coolify URL"
|
||||
helper="URL to your Coolify instance. If it is empty that means you do not have a FQDN set for your Coolify instance." />
|
||||
<x-forms.input canGate="update" :canResource="$server" type="password" id="sentinelToken"
|
||||
label="Sentinel token" required helper="Token for Sentinel." />
|
||||
<x-forms.button canGate="update" :canResource="$server"
|
||||
wire:click="regenerateSentinelToken">Regenerate</x-forms.button>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="flex flex-wrap gap-2 sm:flex-nowrap">
|
||||
<x-forms.input canGate="update" :canResource="$server" type="number" min="1"
|
||||
id="sentinelMetricsRefreshRateSeconds" label="Metrics rate (seconds)" required
|
||||
helper="Interval used for gathering metrics. Lower values result in more disk space usage." />
|
||||
<x-forms.input canGate="update" :canResource="$server" type="number" min="1"
|
||||
id="sentinelMetricsHistoryDays"
|
||||
label="Metrics history (days)" required
|
||||
helper="Number of days to retain metrics data for." />
|
||||
<x-forms.input canGate="update" :canResource="$server" type="number" min="10"
|
||||
id="sentinelPushIntervalSeconds" label="Push interval (seconds)" required
|
||||
helper="Interval at which metrics data is sent to the collector." />
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
<div>
|
||||
<x-slot:title>
|
||||
Sentinel Logs | Coolify
|
||||
</x-slot>
|
||||
<livewire:server.navbar :server="$server" />
|
||||
<div class="flex flex-col h-full gap-8 sm:flex-row">
|
||||
<x-server.sidebar-sentinel :server="$server" :parameters="$parameters" />
|
||||
<div class="w-full">
|
||||
<h2 class="pb-4">Logs</h2>
|
||||
<livewire:project.shared.get-logs :server="$server" container="coolify-sentinel" displayName="Sentinel" :collapsible="false" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,16 @@
|
||||
<div>
|
||||
<x-slot:title>
|
||||
Sentinel Configuration | Coolify
|
||||
</x-slot>
|
||||
<livewire:server.navbar :server="$server" />
|
||||
@if ($server->isFunctional())
|
||||
<div class="flex flex-col h-full gap-8 sm:flex-row">
|
||||
<x-server.sidebar-sentinel :server="$server" :parameters="$parameters" />
|
||||
<div class="w-full">
|
||||
<livewire:server.sentinel :server="$server" />
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
<div>Server is not validated. Validate first.</div>
|
||||
@endif
|
||||
</div>
|
||||
+5
-3
@@ -57,7 +57,8 @@ use App\Livewire\Server\Proxy\Show as ProxyShow;
|
||||
use App\Livewire\Server\Resources as ResourcesShow;
|
||||
use App\Livewire\Server\Security\Patches;
|
||||
use App\Livewire\Server\Security\TerminalAccess;
|
||||
use App\Livewire\Server\Sentinel as ServerSentinel;
|
||||
use App\Livewire\Server\Sentinel\Logs as SentinelLogs;
|
||||
use App\Livewire\Server\Sentinel\Show as SentinelShow;
|
||||
use App\Livewire\Server\Show as ServerShow;
|
||||
use App\Livewire\Server\Swarm as ServerSwarm;
|
||||
use App\Livewire\Settings\Advanced as SettingsAdvanced;
|
||||
@@ -281,7 +282,8 @@ Route::middleware(['auth', 'verified'])->group(function () {
|
||||
Route::get('/', ServerShow::class)->name('server.show');
|
||||
Route::get('/advanced', ServerAdvanced::class)->name('server.advanced');
|
||||
Route::get('/swarm', ServerSwarm::class)->name('server.swarm');
|
||||
Route::get('/sentinel', ServerSentinel::class)->name('server.sentinel');
|
||||
Route::get('/sentinel', SentinelShow::class)->name('server.sentinel');
|
||||
Route::get('/sentinel/logs', SentinelLogs::class)->name('server.sentinel.logs');
|
||||
Route::get('/private-key', PrivateKeyShow::class)->name('server.private-key');
|
||||
Route::get('/cloud-provider-token', CloudProviderTokenShow::class)->name('server.cloud-provider-token');
|
||||
Route::get('/ca-certificate', CaCertificateShow::class)->name('server.ca-certificate');
|
||||
@@ -289,7 +291,7 @@ Route::middleware(['auth', 'verified'])->group(function () {
|
||||
Route::get('/cloudflare-tunnel', CloudflareTunnel::class)->name('server.cloudflare-tunnel');
|
||||
Route::get('/destinations', ServerDestinations::class)->name('server.destinations');
|
||||
Route::get('/log-drains', LogDrains::class)->name('server.log-drains');
|
||||
Route::get('/metrics', ServerCharts::class)->name('server.charts');
|
||||
Route::get('/metrics', ServerCharts::class)->name('server.metrics');
|
||||
Route::get('/danger', DeleteServer::class)->name('server.delete');
|
||||
Route::get('/proxy', ProxyShow::class)->name('server.proxy');
|
||||
Route::get('/proxy/dynamic', ProxyDynamicConfigurations::class)->name('server.proxy.dynamic-confs');
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
it('keeps sentinel restarted events from re-syncing editable form fields', function () {
|
||||
$componentSource = file_get_contents(app_path('Livewire/Server/Sentinel.php'));
|
||||
|
||||
preg_match('/public function handleSentinelRestarted\([^)]*\)\s*\{(?<body>.*?)\n \}/s', $componentSource, $matches);
|
||||
|
||||
expect($matches['body'] ?? '')
|
||||
->toContain('$this->sentinelUpdatedAt = $this->server->sentinel_updated_at;')
|
||||
->not->toContain('$this->syncData();');
|
||||
});
|
||||
|
||||
it('dispatches a server navbar refresh after toggling sentinel', function () {
|
||||
$componentSource = file_get_contents(app_path('Livewire/Server/Sentinel.php'));
|
||||
|
||||
preg_match('/public function toggleSentinel\([^)]*\).*?\{(?<body>.*?)
|
||||
\}/s', $componentSource, $matches);
|
||||
|
||||
expect($matches['body'] ?? '')
|
||||
->toContain("\$this->dispatch('refreshServerShow');");
|
||||
});
|
||||
Reference in New Issue
Block a user