fix: server validation process

This commit is contained in:
Andras Bacsai 2023-10-09 11:00:18 +02:00
parent 5b584a6c6d
commit dcaa7a6ad7
30 changed files with 321 additions and 149 deletions

View file

@ -2,12 +2,14 @@
namespace App\Actions\Server; namespace App\Actions\Server;
use Lorisleiva\Actions\Concerns\AsAction;
use App\Models\Server; use App\Models\Server;
use App\Models\StandaloneDocker; use App\Models\StandaloneDocker;
class InstallDocker class InstallDocker
{ {
public function __invoke(Server $server) use AsAction;
public function handle(Server $server)
{ {
$dockerVersion = '24.0'; $dockerVersion = '24.0';
$config = base64_encode('{ $config = base64_encode('{

View file

@ -1,32 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Models\PrivateKey;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Validation\ValidatesRequests;
class ServerController extends Controller
{
use AuthorizesRequests, ValidatesRequests;
public function new_server()
{
$privateKeys = PrivateKey::ownedByCurrentTeam()->get();
if (!isCloud()) {
return view('server.create', [
'limit_reached' => false,
'private_keys' => $privateKeys,
]);
}
$team = currentTeam();
$servers = $team->servers->count();
['serverLimit' => $serverLimit] = $team->limits;
$limit_reached = $servers >= $serverLimit;
return view('server.create', [
'limit_reached' => $limit_reached,
'private_keys' => $privateKeys,
]);
}
}

View file

@ -220,7 +220,7 @@ public function validateServer()
public function installDocker() public function installDocker()
{ {
$this->dockerInstallationStarted = true; $this->dockerInstallationStarted = true;
$activity = resolve(InstallDocker::class)($this->createdServer); $activity = InstallDocker::run($this->createdServer);
$this->emit('newMonitorActivity', $activity->id); $this->emit('newMonitorActivity', $activity->id);
} }
public function dockerInstalledOrSkipped() public function dockerInstalledOrSkipped()

View file

@ -0,0 +1,29 @@
<?php
namespace App\Http\Livewire\Server;
use App\Models\PrivateKey;
use Livewire\Component;
class Create extends Component
{
public $private_keys = [];
public bool $limit_reached = false;
public function mount()
{
$this->private_keys = PrivateKey::ownedByCurrentTeam()->get();
if (!isCloud()) {
$this->limit_reached = false;
return;
}
$team = currentTeam();
$servers = $team->servers->count();
['serverLimit' => $serverLimit] = $team->limits;
$this->limit_reached = $servers >= $serverLimit;
}
public function render()
{
return view('livewire.server.create');
}
}

View file

@ -0,0 +1,28 @@
<?php
namespace App\Http\Livewire\Server\Destination;
use App\Models\Server;
use Livewire\Component;
class Show extends Component
{
public ?Server $server = null;
public $parameters = [];
public function mount()
{
$this->parameters = get_route_parameters();
try {
$this->server = Server::ownedByCurrentTeam(['name', 'proxy'])->whereUuid(request()->server_uuid)->first();
if (is_null($this->server)) {
return redirect()->route('server.all');
}
} catch (\Throwable $e) {
return handleError($e, $this);
}
}
public function render()
{
return view('livewire.server.destination.show');
}
}

View file

@ -11,11 +11,12 @@ class Form extends Component
{ {
use AuthorizesRequests; use AuthorizesRequests;
public Server $server; public Server $server;
public $uptime; public bool $isValidConnection = false;
public $dockerVersion; public bool $isValidDocker = false;
public string|null $wildcard_domain = null; public ?string $wildcard_domain = null;
public int $cleanup_after_percentage; public int $cleanup_after_percentage;
public bool $dockerInstallationStarted = false; public bool $dockerInstallationStarted = false;
protected $listeners = ['serverRefresh'];
protected $rules = [ protected $rules = [
'server.name' => 'required|min:6', 'server.name' => 'required|min:6',
@ -44,37 +45,49 @@ public function mount()
$this->wildcard_domain = $this->server->settings->wildcard_domain; $this->wildcard_domain = $this->server->settings->wildcard_domain;
$this->cleanup_after_percentage = $this->server->settings->cleanup_after_percentage; $this->cleanup_after_percentage = $this->server->settings->cleanup_after_percentage;
} }
public function instantSave() { public function serverRefresh() {
$this->validateServer();
}
public function instantSave()
{
refresh_server_connection($this->server->privateKey); refresh_server_connection($this->server->privateKey);
$this->validateServer(); $this->validateServer();
$this->server->settings->save(); $this->server->settings->save();
} }
public function installDocker() public function installDocker()
{ {
$this->emit('installDocker');
$this->dockerInstallationStarted = true; $this->dockerInstallationStarted = true;
$activity = resolve(InstallDocker::class)($this->server); $activity = InstallDocker::run($this->server);
$this->emit('newMonitorActivity', $activity->id); $this->emit('newMonitorActivity', $activity->id);
} }
public function validateServer() public function validateServer($install = true)
{ {
try { try {
['uptime' => $uptime, 'dockerVersion' => $dockerVersion] = validateServer($this->server, true); $uptime = $this->server->validateConnection();
if ($uptime) { if ($uptime) {
$this->uptime = $uptime; $install && $this->emit('success', 'Server is reachable.');
$this->emit('success', 'Server is reachable.');
} else { } else {
$this->emit('error', 'Server is not reachable.'); $install &&$this->emit('error', 'Server is not reachable. Please check your connection and private key configuration.');
return; return;
} }
if ($dockerVersion) { $dockerInstalled = $this->server->validateDockerEngine();
$this->dockerVersion = $dockerVersion; if ($dockerInstalled) {
$this->emit('success', 'Docker Engine 23+ is installed!'); $install && $this->emit('success', 'Docker Engine is installed.<br> Checking version.');
} else { } else {
$this->emit('error', 'No Docker Engine or older than 23 version installed.'); $install && $this->installDocker();
return;
}
$dockerVersion = $this->server->validateDockerEngineVersion();
if ($dockerVersion) {
$install && $this->emit('success', 'Docker Engine version is 23+.');
} else {
$install && $this->installDocker();
return;
} }
} catch (\Throwable $e) { } catch (\Throwable $e) {
return handleError($e, $this, customErrorMessage: "Server is not reachable: "); return handleError($e, $this);
} finally { } finally {
$this->emit('proxyStatusUpdated'); $this->emit('proxyStatusUpdated');
} }

View file

@ -0,0 +1,31 @@
<?php
namespace App\Http\Livewire\Server\PrivateKey;
use App\Models\PrivateKey;
use App\Models\Server;
use Livewire\Component;
class Show extends Component
{
public ?Server $server = null;
public $privateKeys = [];
public $parameters = [];
public function mount()
{
$this->parameters = get_route_parameters();
try {
$this->server = Server::ownedByCurrentTeam(['name', 'proxy'])->whereUuid(request()->server_uuid)->first();
if (is_null($this->server)) {
return redirect()->route('server.all');
}
$this->privateKeys = PrivateKey::ownedByCurrentTeam()->get()->where('is_git_related', false);
} catch (\Throwable $e) {
return handleError($e, $this);
}
}
public function render()
{
return view('livewire.server.private-key.show');
}
}

View file

@ -11,7 +11,7 @@ class Deploy extends Component
public Server $server; public Server $server;
public bool $traefikDashboardAvailable = false; public bool $traefikDashboardAvailable = false;
public ?string $currentRoute = null; public ?string $currentRoute = null;
protected $listeners = ['proxyStatusUpdated', 'traefikDashboardAvailable']; protected $listeners = ['proxyStatusUpdated', 'traefikDashboardAvailable', 'serverRefresh' => 'proxyStatusUpdated'];
public function mount() { public function mount() {
$this->currentRoute = request()->route()->getName(); $this->currentRoute = request()->route()->getName();

View file

@ -0,0 +1,28 @@
<?php
namespace App\Http\Livewire\Server\Proxy;
use App\Models\Server;
use Livewire\Component;
class Show extends Component
{
public ?Server $server = null;
public $parameters = [];
public function mount()
{
$this->parameters = get_route_parameters();
try {
$this->server = Server::ownedByCurrentTeam(['name', 'proxy'])->whereUuid(request()->server_uuid)->first();
if (is_null($this->server)) {
return redirect()->route('server.all');
}
} catch (\Throwable $e) {
return handleError($e, $this);
}
}
public function render()
{
return view('livewire.server.proxy.show');
}
}

View file

@ -26,7 +26,9 @@ public function getProxyStatus()
} }
public function getProxyStatusWithNoti() public function getProxyStatusWithNoti()
{ {
$this->emit('success', 'Refreshed proxy status.'); if ($this->server->isFunctional()) {
$this->getProxyStatus(); $this->emit('success', 'Refreshed proxy status.');
$this->getProxyStatus();
}
} }
} }

View file

@ -10,8 +10,10 @@ class Show extends Component
{ {
use AuthorizesRequests; use AuthorizesRequests;
public ?Server $server = null; public ?Server $server = null;
public $parameters = [];
public function mount() public function mount()
{ {
$this->parameters = get_route_parameters();
try { try {
$this->server = Server::ownedByCurrentTeam(['name', 'description', 'ip', 'port', 'user', 'proxy'])->whereUuid(request()->server_uuid)->first(); $this->server = Server::ownedByCurrentTeam(['name', 'description', 'ip', 'port', 'user', 'proxy'])->whereUuid(request()->server_uuid)->first();
if (is_null($this->server)) { if (is_null($this->server)) {
@ -21,6 +23,10 @@ public function mount()
return handleError($e, $this); return handleError($e, $this);
} }
} }
public function submit()
{
$this->emit('serverRefresh');
}
public function render() public function render()
{ {
return view('livewire.server.show'); return view('livewire.server.show');

View file

@ -32,36 +32,34 @@ public function setPrivateKey($newPrivateKeyId)
} }
} }
public function checkConnection() public function checkConnection($install = false)
{ {
try { try {
['uptime' => $uptime, 'dockerVersion' => $dockerVersion] = validateServer($this->server, true); $uptime = $this->server->validateConnection();
if ($uptime) { if ($uptime) {
$this->server->settings->update([ $install && $this->emit('success', 'Server is reachable.');
'is_reachable' => true
]);
$this->emit('success', 'Server is reachable with this private key.');
} else { } else {
$this->server->settings->update([ $install && $this->emit('error', 'Server is not reachable. Please check your connection and private key configuration.');
'is_reachable' => false,
'is_usable' => false
]);
$this->emit('error', 'Server is not reachable with this private key.');
return; return;
} }
if ($dockerVersion) { $dockerInstalled = $this->server->validateDockerEngine();
$this->server->settings->update([ if ($dockerInstalled) {
'is_usable' => true $install && $this->emit('success', 'Docker Engine is installed.<br> Checking version.');
]);
$this->emit('success', 'Server is usable for Coolify.');
} else { } else {
$this->server->settings->update([ $install && $this->installDocker();
'is_usable' => false return;
]); }
$this->emit('error', 'Old (lower than 23) or no Docker version detected. Install Docker Engine on the General tab.'); $dockerVersion = $this->server->validateDockerEngineVersion();
if ($dockerVersion) {
$install && $this->emit('success', 'Docker Engine version is 23+.');
} else {
$install && $this->installDocker();
return;
} }
} catch (\Throwable $e) { } catch (\Throwable $e) {
return handleError($e, $this); return handleError($e, $this);
} finally {
$this->emit('proxyStatusUpdated');
} }
} }

View file

@ -41,15 +41,7 @@ public function uniqueId(): string
{ {
return $this->server->uuid; return $this->server->uuid;
} }
public function handle()
private function checkServerConnection()
{
$uptime = instant_remote_process(['uptime'], $this->server, false);
if (!is_null($uptime)) {
return true;
}
}
public function handle(): void
{ {
try { try {
ray("checking server status for {$this->server->name}"); ray("checking server status for {$this->server->name}");
@ -57,9 +49,11 @@ public function handle(): void
$serverUptimeCheckNumber = 0; $serverUptimeCheckNumber = 0;
$serverUptimeCheckNumberMax = 3; $serverUptimeCheckNumberMax = 3;
while (true) { while (true) {
ray('checking # ' . $serverUptimeCheckNumber);
if ($serverUptimeCheckNumber >= $serverUptimeCheckNumberMax) { if ($serverUptimeCheckNumber >= $serverUptimeCheckNumberMax) {
send_internal_notification('Server unreachable: ' . $this->server->name); send_internal_notification('Server unreachable: ' . $this->server->name);
if ($this->server->unreachable_email_sent === false) { if ($this->server->unreachable_email_sent === false) {
ray('Server unreachable, sending notification...');
$this->server->team->notify(new Unreachable($this->server)); $this->server->team->notify(new Unreachable($this->server));
} }
$this->server->settings()->update([ $this->server->settings()->update([
@ -68,7 +62,7 @@ public function handle(): void
$this->server->update(['unreachable_email_sent' => true]); $this->server->update(['unreachable_email_sent' => true]);
return; return;
} }
$result = $this->checkServerConnection(); $result = $this->server->validateConnection();
if ($result) { if ($result) {
break; break;
} }
@ -76,6 +70,7 @@ public function handle(): void
sleep(5); sleep(5);
} }
if (data_get($this->server, 'unreachable_email_sent') === true) { if (data_get($this->server, 'unreachable_email_sent') === true) {
ray('Server is reachable again, sending notification...');
$this->server->team->notify(new Revived($this->server)); $this->server->team->notify(new Revived($this->server));
$this->server->update(['unreachable_email_sent' => false]); $this->server->update(['unreachable_email_sent' => false]);
} }
@ -88,7 +83,7 @@ public function handle(): void
'is_usable' => true 'is_usable' => true
]); ]);
} }
$this->server->validateDockerEngine(true);
$containers = instant_remote_process(["docker container ls -q"], $this->server); $containers = instant_remote_process(["docker container ls -q"], $this->server);
if (!$containers) { if (!$containers) {
return; return;
@ -288,7 +283,7 @@ public function handle(): void
} catch (\Throwable $e) { } catch (\Throwable $e) {
send_internal_notification('ContainerStatusJob failed with: ' . $e->getMessage()); send_internal_notification('ContainerStatusJob failed with: ' . $e->getMessage());
ray($e->getMessage()); ray($e->getMessage());
throw $e; return handleError($e);
} }
} }
} }

View file

@ -16,9 +16,11 @@ class Server extends BaseModel
protected static function booted() protected static function booted()
{ {
static::saved(function ($server) { static::saving(function ($server) {
$server->ip = Str::of($server->ip)->trim(); $server->forceFill([
$server->user = Str::of($server->user)->trim(); 'ip' => Str::of($server->ip)->trim(),
'user' => Str::of($server->user)->trim(),
]);
}); });
static::created(function ($server) { static::created(function ($server) {
@ -205,4 +207,48 @@ public function isFunctional()
{ {
return $this->settings->is_reachable && $this->settings->is_usable; return $this->settings->is_reachable && $this->settings->is_usable;
} }
public function validateConnection()
{
$uptime = instant_remote_process(['uptime'], $this, false);
if (!$uptime) {
$this->settings->is_reachable = false;
$this->settings->save();
return false;
}
$this->settings->is_reachable = true;
$this->settings->save();
return true;
}
public function validateDockerEngine($throwError = false)
{
$dockerBinary = instant_remote_process(["command -v docker"], $this, false);
if (is_null($dockerBinary)) {
$this->settings->is_usable = false;
$this->settings->save();
if ($throwError) {
throw new \Exception('Server is not usable.');
}
return false;
}
$this->settings->is_usable = true;
$this->settings->save();
$this->validateCoolifyNetwork();
return true;
}
public function validateDockerEngineVersion()
{
$dockerVersion = instant_remote_process(["docker version|head -2|grep -i version| awk '{print $2}'"], $this, false);
$dockerVersion = checkMinimumDockerEngineVersion($dockerVersion);
if (is_null($dockerVersion)) {
$this->settings->is_usable = false;
$this->settings->save();
return false;
}
$this->settings->is_usable = true;
$this->settings->save();
return true;
}
public function validateCoolifyNetwork() {
return instant_remote_process(["docker network create coolify --attachable >/dev/null 2>&1 || true"], $this, false);
}
} }

View file

@ -4,6 +4,9 @@
use App\Models\Server; use App\Models\Server;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use App\Notifications\Channels\DiscordChannel;
use App\Notifications\Channels\EmailChannel;
use App\Notifications\Channels\TelegramChannel;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification; use Illuminate\Notifications\Notification;
@ -22,7 +25,21 @@ public function __construct(public Server $server)
public function via(object $notifiable): array public function via(object $notifiable): array
{ {
return setNotificationChannels($notifiable, 'status_changes'); $channels = [];
$isEmailEnabled = isEmailEnabled($notifiable);
$isDiscordEnabled = data_get($notifiable, 'discord_enabled');
$isTelegramEnabled = data_get($notifiable, 'telegram_enabled');
if ($isDiscordEnabled) {
$channels[] = DiscordChannel::class;
}
if ($isEmailEnabled ) {
$channels[] = EmailChannel::class;
}
if ($isTelegramEnabled) {
$channels[] = TelegramChannel::class;
}
return $channels;
} }
public function toMail(): MailMessage public function toMail(): MailMessage

View file

@ -3,6 +3,9 @@
namespace App\Notifications\Server; namespace App\Notifications\Server;
use App\Models\Server; use App\Models\Server;
use App\Notifications\Channels\DiscordChannel;
use App\Notifications\Channels\EmailChannel;
use App\Notifications\Channels\TelegramChannel;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Notifications\Messages\MailMessage;
@ -20,7 +23,21 @@ public function __construct(public Server $server)
public function via(object $notifiable): array public function via(object $notifiable): array
{ {
return setNotificationChannels($notifiable, 'status_changes'); $channels = [];
$isEmailEnabled = isEmailEnabled($notifiable);
$isDiscordEnabled = data_get($notifiable, 'discord_enabled');
$isTelegramEnabled = data_get($notifiable, 'telegram_enabled');
if ($isDiscordEnabled) {
$channels[] = DiscordChannel::class;
}
if ($isEmailEnabled ) {
$channels[] = EmailChannel::class;
}
if ($isTelegramEnabled) {
$channels[] = TelegramChannel::class;
}
return $channels;
} }
public function toMail(): MailMessage public function toMail(): MailMessage

View file

@ -56,7 +56,7 @@ .box {
@apply flex items-center p-2 transition-colors cursor-pointer min-h-16 bg-coolgray-200 hover:bg-coollabs-100 hover:text-white hover:no-underline min-w-[24rem]; @apply flex items-center p-2 transition-colors cursor-pointer min-h-16 bg-coolgray-200 hover:bg-coollabs-100 hover:text-white hover:no-underline min-w-[24rem];
} }
.box-without-bg { .box-without-bg {
@apply flex items-center p-2 transition-colors min-h-16 hover:text-white hover:no-underline min-w-[24rem]; @apply flex items-center p-2 transition-colors min-h-16 hover:text-white hover:no-underline min-w-[24rem];
} }
.lds-heart { .lds-heart {

View file

@ -8,25 +8,25 @@
<nav class="navbar-main"> <nav class="navbar-main">
<a class="{{ request()->routeIs('server.show') ? 'text-white' : '' }}" <a class="{{ request()->routeIs('server.show') ? 'text-white' : '' }}"
href="{{ route('server.show', [ href="{{ route('server.show', [
'server_uuid' => Route::current()->parameters()['server_uuid'], 'server_uuid' => data_get($parameters, 'server_uuid'),
]) }}"> ]) }}">
<button>General</button> <button>General</button>
</a> </a>
<a class="{{ request()->routeIs('server.private-key') ? 'text-white' : '' }}" <a class="{{ request()->routeIs('server.private-key') ? 'text-white' : '' }}"
href="{{ route('server.private-key', [ href="{{ route('server.private-key', [
'server_uuid' => Route::current()->parameters()['server_uuid'], 'server_uuid' => data_get($parameters, 'server_uuid'),
]) }}"> ]) }}">
<button>Private Key</button> <button>Private Key</button>
</a> </a>
<a class="{{ request()->routeIs('server.proxy') ? 'text-white' : '' }}" <a class="{{ request()->routeIs('server.proxy') ? 'text-white' : '' }}"
href="{{ route('server.proxy', [ href="{{ route('server.proxy', [
'server_uuid' => Route::current()->parameters()['server_uuid'], 'server_uuid' => data_get($parameters, 'server_uuid'),
]) }}"> ]) }}">
<button>Proxy</button> <button>Proxy</button>
</a> </a>
<a class="{{ request()->routeIs('server.destinations') ? 'text-white' : '' }}" <a class="{{ request()->routeIs('server.destinations') ? 'text-white' : '' }}"
href="{{ route('server.destinations', [ href="{{ route('server.destinations', [
'server_uuid' => Route::current()->parameters()['server_uuid'], 'server_uuid' => data_get($parameters, 'server_uuid'),
]) }}"> ]) }}">
<button>Destinations</button> <button>Destinations</button>
</a> </a>

View file

@ -5,10 +5,6 @@
@if ($containerName === 'coolify-proxy') @if ($containerName === 'coolify-proxy')
Coolify Proxy should run on your server as you have FQDNs set up in one of your resources. Coolify Proxy should run on your server as you have FQDNs set up in one of your resources.
Note: The proxy should not stop unexpectedly, so please check what is going on your server.
If you don't want to use Coolify Proxy, please remove FQDN from your resources or set Proxy type to Custom(None). If you don't want to use Coolify Proxy, please remove FQDN from your resources or set Proxy type to Custom(None).
@endif @endif

View file

@ -0,0 +1,9 @@
<div>
@if ($private_keys->count() === 0)
<h1>Create Private Key</h1>
<div class="subtitle">You need to create a private key before you can create a server.</div>
<livewire:private-key.create from="server" />
@else
<livewire:server.new.by-ip :private_keys="$private_keys" :limit_reached="$limit_reached" />
@endif
</div>

View file

@ -0,0 +1,4 @@
<div>
<x-server.navbar :server="$server" :parameters="$parameters" />
<livewire:destination.show :server="$server" />
</div>

View file

@ -1,4 +1,4 @@
<div> <div x-init="$wire.validateServer(false)">
<x-modal yesOrNo modalId="deleteServer" modalTitle="Delete Server"> <x-modal yesOrNo modalId="deleteServer" modalTitle="Delete Server">
<x-slot:modalBody> <x-slot:modalBody>
<p>This server will be deleted. It is not reversible. <br>Please think again..</p> <p>This server will be deleted. It is not reversible. <br>Please think again..</p>
@ -25,6 +25,11 @@
@else @else
Server is reachable and validated. Server is reachable and validated.
@endif @endif
@if ((!$server->settings->is_reachable || !$server->settings->is_usable) && $server->id !== 0)
<x-forms.button class="mt-8 mb-4 font-bold box-without-bg bg-coollabs hover:bg-coollabs-100" wire:click.prevent='validateServer' isHighlighted>
Validate Server & Install Docker Engine
</x-forms.button>
@endif
<div class="flex flex-col gap-2 pt-4"> <div class="flex flex-col gap-2 pt-4">
<div class="flex flex-col w-full gap-2 lg:flex-row"> <div class="flex flex-col w-full gap-2 lg:flex-row">
<x-forms.input id="server.name" label="Name" required /> <x-forms.input id="server.name" label="Name" required />
@ -42,27 +47,12 @@
</div> </div>
</div> </div>
<div class="w-64"> <div class="w-64">
<x-forms.checkbox instantSave helper="If you are using Cloudflare Tunnels, enable this. It will proxy all ssh requests to your server through Cloudflare.<span class='text-warning'>Coolify does not install/setup Cloudflare (cloudflared) on your server.</span>" <x-forms.checkbox instantSave
helper="If you are using Cloudflare Tunnels, enable this. It will proxy all ssh requests to your server through Cloudflare.<span class='text-warning'>Coolify does not install/setup Cloudflare (cloudflared) on your server.</span>"
id="server.settings.is_cloudflare_tunnel" label="Cloudflare Tunnel" /> id="server.settings.is_cloudflare_tunnel" label="Cloudflare Tunnel" />
</div> </div>
</div> </div>
@if (!$server->settings->is_reachable)
<x-forms.button class="mt-8 mb-4 box" wire:click.prevent='validateServer'>
Validate Server
</x-forms.button>
@endif
@if ($server->settings->is_reachable && !$server->settings->is_usable && $server->id !== 0)
@if ($dockerInstallationStarted)
<x-forms.button class="mt-8 mb-4 box" wire:click.prevent='validateServer'>
Validate Server
</x-forms.button>
@else
<x-forms.button class="mt-8 mb-4 box" onclick="installDocker.showModal()"
wire:click.prevent='installDocker' isHighlighted>
Install Docker Engine 24.0
</x-forms.button>
@endif
@endif
@if ($server->isFunctional()) @if ($server->isFunctional())
<h3 class="py-4">Settings</h3> <h3 class="py-4">Settings</h3>
<x-forms.input id="cleanup_after_percentage" label="Disk Cleanup threshold (%)" required <x-forms.input id="cleanup_after_percentage" label="Disk Cleanup threshold (%)" required
@ -80,4 +70,11 @@
Delete Delete
</x-forms.button> </x-forms.button>
@endif @endif
<script>
Livewire.on('installDocker', () => {
console.log('asd');
installDocker.showModal();
})
</script>
</div> </div>

View file

@ -1,4 +1,4 @@
<x-layout> <div>
<x-server.navbar :server="$server" /> <x-server.navbar :server="$server" :parameters="$parameters" />
<livewire:server.show-private-key :server="$server" :privateKeys="$privateKeys" /> <livewire:server.show-private-key :server="$server" :privateKeys="$privateKeys" />
</x-layout> </div>

View file

@ -0,0 +1,4 @@
<div>
<x-server.navbar :server="$server" :parameters="$parameters" />
<livewire:server.proxy :server="$server" />
</div>

View file

@ -1,7 +1,7 @@
<div> <div>
<x-modal noSubmit modalId="installDocker"> <x-modal modalId="installDocker">
<x-slot:modalBody> <x-slot:modalBody>
<livewire:activity-monitor header="Installation Logs" /> <livewire:activity-monitor header="Docker Installation Logs" />
</x-slot:modalBody> </x-slot:modalBody>
<x-slot:modalSubmit> <x-slot:modalSubmit>
<x-forms.button onclick="installDocker.close()" type="submit"> <x-forms.button onclick="installDocker.close()" type="submit">
@ -9,6 +9,6 @@
</x-forms.button> </x-forms.button>
</x-slot:modalSubmit> </x-slot:modalSubmit>
</x-modal> </x-modal>
<x-server.navbar :server="$server" /> <x-server.navbar :server="$server" :parameters="$parameters" />
<livewire:server.form :server="$server" /> <livewire:server.form :server="$server" />
</div> </div>

View file

@ -1,3 +0,0 @@
<x-layout>
</x-layout>

View file

@ -1,4 +0,0 @@
<x-layout>
<x-server.navbar :server="$server" />
<livewire:destination.show :server="$server" />
</x-layout>

View file

@ -1,4 +0,0 @@
<x-layout>
<x-server.navbar :server="$server" />
<livewire:server.proxy :server="$server" />
</x-layout>

View file

@ -1,4 +0,0 @@
<x-layout>
<x-server.navbar :server="$server" />
<livewire:server.form :server="$server" />
</x-layout>

View file

@ -13,6 +13,10 @@
use App\Http\Livewire\Dashboard; use App\Http\Livewire\Dashboard;
use App\Http\Livewire\Project\Shared\Logs; use App\Http\Livewire\Project\Shared\Logs;
use App\Http\Livewire\Server\All; use App\Http\Livewire\Server\All;
use App\Http\Livewire\Server\Create;
use App\Http\Livewire\Server\Destination\Show as DestinationShow;
use App\Http\Livewire\Server\PrivateKey\Show as PrivateKeyShow;
use App\Http\Livewire\Server\Proxy\Show as ProxyShow;
use App\Http\Livewire\Server\Show; use App\Http\Livewire\Server\Show;
use App\Http\Livewire\Waitlist\Index as WaitlistIndex; use App\Http\Livewire\Waitlist\Index as WaitlistIndex;
use App\Models\GithubApp; use App\Models\GithubApp;
@ -102,18 +106,11 @@
Route::middleware(['auth'])->group(function () { Route::middleware(['auth'])->group(function () {
Route::get('/servers', All::class)->name('server.all'); Route::get('/servers', All::class)->name('server.all');
Route::get('/server/new', [ServerController::class, 'new_server'])->name('server.create'); Route::get('/server/new', Create::class)->name('server.create');
Route::get('/server/{server_uuid}', Show::class)->name('server.show'); Route::get('/server/{server_uuid}', Show::class)->name('server.show');
Route::get('/server/{server_uuid}/proxy', fn () => view('server.proxy', [ Route::get('/server/{server_uuid}/proxy', ProxyShow::class)->name('server.proxy');
'server' => Server::ownedByCurrentTeam(['name', 'proxy'])->whereUuid(request()->server_uuid)->firstOrFail(), Route::get('/server/{server_uuid}/private-key', PrivateKeyShow::class)->name('server.private-key');
]))->name('server.proxy'); Route::get('/server/{server_uuid}/destinations', DestinationShow::class)->name('server.destinations');
Route::get('/server/{server_uuid}/private-key', fn () => view('server.private-key', [
'server' => Server::ownedByCurrentTeam()->whereUuid(request()->server_uuid)->firstOrFail(),
'privateKeys' => PrivateKey::ownedByCurrentTeam()->get()->where('is_git_related', false),
]))->name('server.private-key');
Route::get('/server/{server_uuid}/destinations', fn () => view('server.destinations', [
'server' => Server::ownedByCurrentTeam(['name', 'proxy'])->whereUuid(request()->server_uuid)->firstOrFail()
]))->name('server.destinations');
}); });