fixes for terminal
This commit is contained in:
@@ -11,17 +11,19 @@ class Terminal extends Component
|
||||
#[On('send-terminal-command')]
|
||||
public function sendTerminalCommand($isContainer, $identifier, $serverUuid)
|
||||
{
|
||||
$server = Server::whereUuid($serverUuid)->firstOrFail();
|
||||
$server = Server::ownedByCurrentTeam()->whereUuid($serverUuid)->firstOrFail();
|
||||
|
||||
if (auth()->user()) {
|
||||
$teams = auth()->user()->teams->pluck('id');
|
||||
if (! $teams->contains($server->team_id) && ! $teams->contains(0)) {
|
||||
throw new \Exception('User is not part of the team that owns this server');
|
||||
}
|
||||
}
|
||||
// if (auth()->user()) {
|
||||
// $teams = auth()->user()->teams->pluck('id');
|
||||
// if (! $teams->contains($server->team_id) && ! $teams->contains(0)) {
|
||||
// throw new \Exception('User is not part of the team that owns this server');
|
||||
// }
|
||||
// }
|
||||
|
||||
if ($isContainer) {
|
||||
ray($identifier);
|
||||
$status = getContainerStatus($server, $identifier);
|
||||
ray($status);
|
||||
if ($status !== 'running') {
|
||||
return handleError(new \Exception('Container is not running'), $this);
|
||||
}
|
||||
|
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Livewire;
|
||||
|
||||
use App\Models\Server;
|
||||
use Livewire\Attributes\On;
|
||||
use Livewire\Component;
|
||||
|
||||
@@ -23,7 +22,7 @@ class RunCommand extends Component
|
||||
|
||||
private function getAllActiveContainers()
|
||||
{
|
||||
return Server::all()->flatMap(function ($server) {
|
||||
return collect($this->servers)->flatMap(function ($server) {
|
||||
if (! $server->isFunctional()) {
|
||||
return [];
|
||||
}
|
||||
@@ -31,25 +30,52 @@ class RunCommand extends Component
|
||||
return $server->definedResources()
|
||||
->filter(function ($resource) {
|
||||
$status = method_exists($resource, 'realStatus') ? $resource->realStatus() : (method_exists($resource, 'status') ? $resource->status() : 'exited');
|
||||
|
||||
return str_starts_with($status, 'running:');
|
||||
})
|
||||
->map(function ($resource) use ($server) {
|
||||
$container_name = $resource->uuid;
|
||||
if (isDev()) {
|
||||
if (data_get($resource, 'name') === 'coolify-db') {
|
||||
$container_name = 'coolify-db';
|
||||
|
||||
if (class_basename($resource) === 'Application' || class_basename($resource) === 'Service') {
|
||||
return [
|
||||
'name' => $resource->name,
|
||||
'connection_name' => $container_name,
|
||||
'uuid' => $resource->uuid,
|
||||
'status' => 'running',
|
||||
'server' => $server,
|
||||
'server_uuid' => $server->uuid,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if (class_basename($resource) === 'Application') {
|
||||
if (! $server->isSwarm()) {
|
||||
$current_containers = getCurrentApplicationContainerStatus($server, $resource->id, includePullrequests: true);
|
||||
}
|
||||
$status = $resource->status;
|
||||
} elseif (class_basename($resource) === 'Service') {
|
||||
$current_containers = getCurrentServiceContainerStatus($server, $resource->id);
|
||||
$status = $resource->status();
|
||||
} else {
|
||||
$status = getContainerStatus($server, $resource->uuid);
|
||||
if ($status === 'running') {
|
||||
$current_containers = collect([
|
||||
'Names' => $resource->name,
|
||||
]);
|
||||
}
|
||||
}
|
||||
if ($server->isSwarm()) {
|
||||
$container_name = $resource->uuid.'_'.$resource->uuid;
|
||||
} else {
|
||||
$current_containers = getCurrentApplicationContainerStatus($server, $resource->id, includePullrequests: true);
|
||||
$container_name = data_get($current_containers->first(), 'Names');
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'name' => $resource->name,
|
||||
'connection_name' => $container_name,
|
||||
'uuid' => $resource->uuid,
|
||||
'status' => $resource->status,
|
||||
'status' => $status,
|
||||
'server' => $server,
|
||||
'server_uuid' => $server->uuid,
|
||||
];
|
||||
|
@@ -40,6 +40,20 @@ function getCurrentApplicationContainerStatus(Server $server, int $id, ?int $pul
|
||||
return $containers;
|
||||
}
|
||||
|
||||
function getCurrentServiceContainerStatus(Server $server, int $id): Collection
|
||||
{
|
||||
$containers = collect([]);
|
||||
if (! $server->isSwarm()) {
|
||||
$containers = instant_remote_process(["docker ps -a --filter='label=coolify.serviceId={$id}' --format '{{json .}}' "], $server);
|
||||
$containers = format_docker_command_output_to_json($containers);
|
||||
$containers = $containers->filter();
|
||||
|
||||
return $containers;
|
||||
}
|
||||
|
||||
return $containers;
|
||||
}
|
||||
|
||||
function format_docker_command_output_to_json($rawOutput): Collection
|
||||
{
|
||||
$outputLines = explode(PHP_EOL, $rawOutput);
|
||||
|
@@ -43,25 +43,23 @@ services:
|
||||
- /data/coolify/_volumes/redis/:/data
|
||||
# - coolify-redis-data-dev:/data
|
||||
soketi:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./docker/coolify-realtime/Dockerfile
|
||||
env_file:
|
||||
- .env
|
||||
ports:
|
||||
- "${FORWARD_SOKETI_PORT:-6001}:6001"
|
||||
- "6002:6002"
|
||||
volumes:
|
||||
- ./docker/soketi-entrypoint/soketi-entrypoint.sh:/soketi-entrypoint.sh
|
||||
- ./package.json:/terminal/package.json
|
||||
- ./package-lock.json:/terminal/package-lock.json
|
||||
- ./terminal-server.js:/terminal/terminal-server.js
|
||||
- ./storage:/var/www/html/storage
|
||||
entrypoint: ["/bin/sh", "/soketi-entrypoint.sh"]
|
||||
environment:
|
||||
SOKETI_DEBUG: "false"
|
||||
SOKETI_DEFAULT_APP_ID: "${PUSHER_APP_ID:-coolify}"
|
||||
SOKETI_DEFAULT_APP_KEY: "${PUSHER_APP_KEY:-coolify}"
|
||||
SOKETI_DEFAULT_APP_SECRET: "${PUSHER_APP_SECRET:-coolify}"
|
||||
vite:
|
||||
image: node:alpine
|
||||
image: node:20
|
||||
pull_policy: always
|
||||
working_dir: /var/www/html
|
||||
# environment:
|
||||
|
@@ -109,6 +109,7 @@ services:
|
||||
retries: 10
|
||||
timeout: 2s
|
||||
soketi:
|
||||
image: 'ghcr.io/coollabsio/coolify-realtime:latest'
|
||||
ports:
|
||||
- "${SOKETI_PORT:-6001}:6001"
|
||||
- "6002:6002"
|
||||
|
@@ -103,7 +103,7 @@ services:
|
||||
retries: 10
|
||||
timeout: 2s
|
||||
soketi:
|
||||
image: 'quay.io/soketi/soketi:1.6-16-alpine'
|
||||
image: 'ghcr.io/coollabsio/coolify-realtime:latest'
|
||||
pull_policy: always
|
||||
container_name: coolify-realtime
|
||||
restart: always
|
||||
|
@@ -24,7 +24,6 @@ services:
|
||||
networks:
|
||||
- coolify
|
||||
soketi:
|
||||
image: 'quay.io/soketi/soketi:1.6-16-alpine'
|
||||
container_name: coolify-realtime
|
||||
restart: always
|
||||
networks:
|
||||
|
9
docker/coolify-realtime/Dockerfile
Normal file
9
docker/coolify-realtime/Dockerfile
Normal file
@@ -0,0 +1,9 @@
|
||||
FROM quay.io/soketi/soketi:1.6-16-alpine
|
||||
WORKDIR /terminal
|
||||
RUN apk add --no-cache openssh-client make g++ python3
|
||||
COPY docker/coolify-realtime/package.json ./
|
||||
RUN npm i
|
||||
RUN npm rebuild node-pty --update-binary
|
||||
COPY docker/coolify-realtime/soketi-entrypoint.sh /soketi-entrypoint.sh
|
||||
COPY docker/coolify-realtime/terminal-server.js /terminal/terminal-server.js
|
||||
ENTRYPOINT ["/bin/sh", "/soketi-entrypoint.sh"]
|
13
docker/coolify-realtime/package.json
Normal file
13
docker/coolify-realtime/package.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@xterm/addon-fit": "^0.10.0",
|
||||
"@xterm/xterm": "^5.5.0",
|
||||
"cookie": "^0.6.0",
|
||||
"axios": "1.7.5",
|
||||
"dotenv": "^16.4.5",
|
||||
"node-pty": "^1.0.0",
|
||||
"ws": "^8.17.0"
|
||||
}
|
||||
}
|
@@ -1,16 +1,4 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Install openssh-client
|
||||
apk add --no-cache openssh-client make g++ python3
|
||||
|
||||
cd /terminal
|
||||
|
||||
# Install npm dependencies
|
||||
npm ci
|
||||
|
||||
# Rebuild node-pty
|
||||
npm rebuild node-pty --update-binary
|
||||
|
||||
# Function to timestamp logs
|
||||
timestamp() {
|
||||
date "+%Y-%m-%d %H:%M:%S"
|
@@ -1,6 +1,7 @@
|
||||
<div x-data="data()">
|
||||
<div x-show="!terminalActive" class="flex items-center justify-center w-full py-4 mx-auto h-[510px]">
|
||||
<div class="w-full h-full border rounded dark:bg-coolgray-100 dark:border-coolgray-300">
|
||||
<div
|
||||
class="w-full h-full bg-white border border-solid rounded dark:text-white dark:bg-coolgray-100 scrollbar border-neutral-300 dark:border-coolgray-300 p-1">
|
||||
<span class="font-mono text-sm text-gray-500 ">(connection closed)</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -34,7 +35,9 @@
|
||||
|
||||
function initializeWebSocket() {
|
||||
if (!socket || socket.readyState === WebSocket.CLOSED) {
|
||||
const url = "{{ str_replace(['http://', 'https://'], '', config('app.url')) }}" || window.location.hostname;
|
||||
let url = "{{ str_replace(['http://', 'https://'], '', config('app.url')) }}" || window.location.hostname;
|
||||
// make sure the port is not included
|
||||
url = url.split(':')[0];
|
||||
socket = new WebSocket((window.location.protocol === 'https:' ? 'wss://' : 'ws://') +
|
||||
url +
|
||||
':6002/terminal');
|
||||
|
Reference in New Issue
Block a user