feat: terminal views for servers

improvement: connect to container if only one available
This commit is contained in:
Andras Bacsai
2024-10-24 12:21:36 +02:00
parent a310a13016
commit 9a227dbad6
5 changed files with 71 additions and 16 deletions

View File

@@ -52,6 +52,7 @@ class ExecuteContainerCommand extends Component
$this->servers = $this->servers->push($server); $this->servers = $this->servers->push($server);
} }
} }
$this->loadContainers();
} elseif (data_get($this->parameters, 'database_uuid')) { } elseif (data_get($this->parameters, 'database_uuid')) {
$this->type = 'database'; $this->type = 'database';
$resource = getResourceByUuid($this->parameters['database_uuid'], data_get(auth()->user()->currentTeam(), 'id')); $resource = getResourceByUuid($this->parameters['database_uuid'], data_get(auth()->user()->currentTeam(), 'id'));
@@ -62,12 +63,18 @@ class ExecuteContainerCommand extends Component
if ($this->resource->destination->server->isFunctional()) { if ($this->resource->destination->server->isFunctional()) {
$this->servers = $this->servers->push($this->resource->destination->server); $this->servers = $this->servers->push($this->resource->destination->server);
} }
$this->loadContainers();
} elseif (data_get($this->parameters, 'service_uuid')) { } elseif (data_get($this->parameters, 'service_uuid')) {
$this->type = 'service'; $this->type = 'service';
$this->resource = Service::where('uuid', $this->parameters['service_uuid'])->firstOrFail(); $this->resource = Service::where('uuid', $this->parameters['service_uuid'])->firstOrFail();
if ($this->resource->server->isFunctional()) { if ($this->resource->server->isFunctional()) {
$this->servers = $this->servers->push($this->resource->server); $this->servers = $this->servers->push($this->resource->server);
} }
$this->loadContainers();
} elseif (data_get($this->parameters, 'server_uuid')) {
$this->type = 'server';
$this->resource = Server::where('uuid', $this->parameters['server_uuid'])->firstOrFail();
$this->server = $this->resource;
} }
} }
@@ -130,6 +137,28 @@ class ExecuteContainerCommand extends Component
if ($this->containers->count() > 0) { if ($this->containers->count() > 0) {
$this->container = $this->containers->first(); $this->container = $this->containers->first();
} }
if ($this->containers->count() === 1) {
$this->selected_container = data_get($this->containers->first(), 'container.Names');
}
}
#[On('connectToServer')]
public function connectToServer()
{
try {
if ($this->server->isForceDisabled()) {
throw new \RuntimeException('Server is disabled.');
}
$this->dispatch(
'send-terminal-command',
false,
data_get($this->server, 'name'),
data_get($this->server, 'uuid')
);
} catch (\Throwable $e) {
return handleError($e, $this);
}
} }
#[On('connectToContainer')] #[On('connectToContainer')]

View File

@@ -131,6 +131,11 @@ class Server extends BaseModel
protected $guarded = []; protected $guarded = [];
public function type()
{
return 'server';
}
public static function isReachable() public static function isReachable()
{ {
return Server::ownedByCurrentTeam()->whereRelation('settings', 'is_reachable', true); return Server::ownedByCurrentTeam()->whereRelation('settings', 'is_reachable', true);

View File

@@ -39,6 +39,12 @@
]) }}"> ]) }}">
<button>Resources</button> <button>Resources</button>
</a> </a>
<a class="{{ request()->routeIs('server.command') ? 'dark:text-white' : '' }}"
href="{{ route('server.command', [
'server_uuid' => data_get($parameters, 'server_uuid'),
]) }}">
<button>Terminal</button>
</a>
</nav> </nav>
<div class="order-first sm:order-last"> <div class="order-first sm:order-last">
<livewire:server.proxy.deploy :server="$server" /> <livewire:server.proxy.deploy :server="$server" />

View File

@@ -2,24 +2,36 @@
<x-slot:title> <x-slot:title>
{{ data_get_str($resource, 'name')->limit(10) }} > Commands | Coolify {{ data_get_str($resource, 'name')->limit(10) }} > Commands | Coolify
</x-slot> </x-slot>
<livewire:project.shared.configuration-checker :resource="$resource" />
@if ($type === 'application') @if ($type === 'application')
<livewire:project.shared.configuration-checker :resource="$resource" />
<h1>Terminal</h1> <h1>Terminal</h1>
<livewire:project.application.heading :application="$resource" /> <livewire:project.application.heading :application="$resource" />
@elseif ($type === 'database') @elseif ($type === 'database')
<livewire:project.shared.configuration-checker :resource="$resource" />
<h1>Terminal</h1> <h1>Terminal</h1>
<livewire:project.database.heading :database="$resource" /> <livewire:project.database.heading :database="$resource" />
@elseif ($type === 'service') @elseif ($type === 'service')
<livewire:project.shared.configuration-checker :resource="$resource" />
<livewire:project.service.navbar :service="$resource" :parameters="$parameters" title="Terminal" /> <livewire:project.service.navbar :service="$resource" :parameters="$parameters" title="Terminal" />
@elseif ($type === 'server')
<x-server.navbar :server="$server" :parameters="$parameters" />
@endif @endif
<div x-init="$wire.loadContainers"> @if ($type === 'server')
<div class="pt-4" wire:loading wire:target='loadContainers'> <form class="w-full" wire:submit="$dispatchSelf('connectToServer')" wire:init="$dispatchSelf('connectToServer')">
Loading resources... <x-forms.button class="w-full" type="submit">Reconnect</x-forms.button>
</form>
<div class="mx-auto w-full">
<livewire:project.shared.terminal />
</div> </div>
<div wire:loading.remove wire:target='loadContainers'> @else
@if (count($containers) > 0) @if (count($containers) > 0)
<form class="flex flex-col gap-2 justify-center pt-4 xl:items-end xl:flex-row" @if (count($containers) === 1)
wire:submit="$dispatchSelf('connectToContainer')"> <form class="w-full pt-4"
wire:submit="$dispatchSelf('connectToContainer')" wire:init="$dispatchSelf('connectToContainer')">
<x-forms.button class="w-full" type="submit">Reconnect</x-forms.button>
</form>
@else
<form class="w-full pt-4 flex gap-2 flex-col" wire:submit="$dispatchSelf('connectToContainer')">
<x-forms.select label="Container" id="container" required wire:model="selected_container"> <x-forms.select label="Container" id="container" required wire:model="selected_container">
@foreach ($containers as $container) @foreach ($containers as $container)
@if ($loop->first) @if ($loop->first)
@@ -31,14 +43,16 @@
</option> </option>
@endforeach @endforeach
</x-forms.select> </x-forms.select>
<x-forms.button type="submit">Connect</x-forms.button> <x-forms.button class="w-full" type="submit">
Connect
</x-forms.button>
</form> </form>
@else
<div class="pt-4">No containers are running.</div>
@endif @endif
</div> <div class="mx-auto w-full">
</div> <livewire:project.shared.terminal />
<div class="mx-auto w-full"> </div>
<livewire:project.shared.terminal /> @else
</div> <div class="pt-4">No containers are running.</div>
@endif
@endif
</div> </div>

View File

@@ -212,6 +212,7 @@ Route::middleware(['auth', 'verified'])->group(function () {
Route::get('/private-key', PrivateKeyShow::class)->name('server.private-key'); Route::get('/private-key', PrivateKeyShow::class)->name('server.private-key');
Route::get('/destinations', DestinationShow::class)->name('server.destinations'); Route::get('/destinations', DestinationShow::class)->name('server.destinations');
Route::get('/log-drains', LogDrains::class)->name('server.log-drains'); Route::get('/log-drains', LogDrains::class)->name('server.log-drains');
Route::get('/terminal', ExecuteContainerCommand::class)->name('server.command');
}); });
// Route::get('/security', fn () => view('security.index'))->name('security.index'); // Route::get('/security', fn () => view('security.index'))->name('security.index');