Revert "rector: arrrrr"

This reverts commit 16c0cd10d8.
This commit is contained in:
Andras Bacsai
2025-01-07 15:31:43 +01:00
parent da07b4fdcf
commit 1fe4dd722b
349 changed files with 3689 additions and 4184 deletions

View File

@@ -4,7 +4,6 @@ namespace App\Actions\Application;
use App\Actions\Server\CleanupDocker;
use App\Models\Application;
use Exception;
use Lorisleiva\Actions\Concerns\AsAction;
class StopApplication
@@ -24,7 +23,7 @@ class StopApplication
if ($server->isSwarm()) {
instant_remote_process(["docker stack rm {$application->uuid}"], $server);
return null;
return;
}
$containersToStop = $application->getContainersToStop($previewDeployments);
@@ -37,10 +36,8 @@ class StopApplication
if ($dockerCleanup) {
CleanupDocker::dispatch($server, true);
}
} catch (Exception $e) {
} catch (\Exception $e) {
return $e->getMessage();
}
return null;
}
}

View File

@@ -4,7 +4,6 @@ namespace App\Actions\Application;
use App\Models\Application;
use App\Models\Server;
use Exception;
use Lorisleiva\Actions\Concerns\AsAction;
class StopApplicationOneServer
@@ -14,7 +13,7 @@ class StopApplicationOneServer
public function handle(Application $application, Server $server)
{
if ($application->destination->server->isSwarm()) {
return null;
return;
}
if (! $server->isFunctional()) {
return 'Server is not functional';
@@ -32,10 +31,8 @@ class StopApplicationOneServer
}
}
}
} catch (Exception $e) {
} catch (\Exception $e) {
return $e->getMessage();
}
return null;
}
}

View File

@@ -4,7 +4,6 @@ namespace App\Actions\CoolifyTask;
use App\Data\CoolifyTaskArgs;
use App\Jobs\CoolifyTask;
use Illuminate\Database\Eloquent\Model;
use Spatie\Activitylog\Models\Activity;
/**
@@ -18,36 +17,36 @@ class PrepareCoolifyTask
protected CoolifyTaskArgs $remoteProcessArgs;
public function __construct(CoolifyTaskArgs $coolifyTaskArgs)
public function __construct(CoolifyTaskArgs $remoteProcessArgs)
{
$this->remoteProcessArgs = $coolifyTaskArgs;
$this->remoteProcessArgs = $remoteProcessArgs;
if ($coolifyTaskArgs->model instanceof Model) {
$properties = $coolifyTaskArgs->toArray();
if ($remoteProcessArgs->model) {
$properties = $remoteProcessArgs->toArray();
unset($properties['model']);
$this->activity = activity()
->withProperties($properties)
->performedOn($coolifyTaskArgs->model)
->event($coolifyTaskArgs->type)
->performedOn($remoteProcessArgs->model)
->event($remoteProcessArgs->type)
->log('[]');
} else {
$this->activity = activity()
->withProperties($coolifyTaskArgs->toArray())
->event($coolifyTaskArgs->type)
->withProperties($remoteProcessArgs->toArray())
->event($remoteProcessArgs->type)
->log('[]');
}
}
public function __invoke(): Activity
{
$coolifyTask = new CoolifyTask(
$job = new CoolifyTask(
activity: $this->activity,
ignore_errors: $this->remoteProcessArgs->ignore_errors,
call_event_on_finish: $this->remoteProcessArgs->call_event_on_finish,
call_event_data: $this->remoteProcessArgs->call_event_data,
);
dispatch($coolifyTask);
dispatch($job);
$this->activity->refresh();
return $this->activity;

View File

@@ -11,10 +11,7 @@ use Illuminate\Process\ProcessResult;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Process;
use JsonException;
use RuntimeException;
use Spatie\Activitylog\Models\Activity;
use Throwable;
class RunRemoteProcess
{
@@ -24,9 +21,9 @@ class RunRemoteProcess
public bool $ignore_errors;
public $call_event_on_finish;
public $call_event_on_finish = null;
public $call_event_data;
public $call_event_data = null;
protected $time_start;
@@ -44,7 +41,7 @@ class RunRemoteProcess
public function __construct(Activity $activity, bool $hide_from_output = false, bool $ignore_errors = false, $call_event_on_finish = null, $call_event_data = null)
{
if ($activity->getExtraProperty('type') !== ActivityTypes::INLINE->value && $activity->getExtraProperty('type') !== ActivityTypes::COMMAND->value) {
throw new RuntimeException('Incompatible Activity to run a remote command.');
throw new \RuntimeException('Incompatible Activity to run a remote command.');
}
$this->activity = $activity;
@@ -66,7 +63,7 @@ class RunRemoteProcess
associative: true,
flags: JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE
);
} catch (JsonException $exception) {
} catch (\JsonException $exception) {
return '';
}
@@ -82,12 +79,12 @@ class RunRemoteProcess
$status = ProcessStatus::IN_PROGRESS;
$timeout = config('constants.ssh.command_timeout');
$invokedProcess = Process::timeout($timeout)->start($this->getCommand(), $this->handleOutput(...));
$process = Process::timeout($timeout)->start($this->getCommand(), $this->handleOutput(...));
$this->activity->properties = $this->activity->properties->merge([
'process_id' => $invokedProcess->id(),
'process_id' => $process->id(),
]);
$processResult = $invokedProcess->wait();
$processResult = $process->wait();
// $processResult = Process::timeout($timeout)->run($this->getCommand(), $this->handleOutput(...));
if ($this->activity->properties->get('status') === ProcessStatus::ERROR->value) {
$status = ProcessStatus::ERROR;
@@ -114,7 +111,7 @@ class RunRemoteProcess
]);
$this->activity->save();
if ($processResult->exitCode() != 0 && ! $this->ignore_errors) {
throw new RuntimeException($processResult->errorOutput(), $processResult->exitCode());
throw new \RuntimeException($processResult->errorOutput(), $processResult->exitCode());
}
if ($this->call_event_on_finish) {
try {
@@ -127,7 +124,7 @@ class RunRemoteProcess
'userId' => $this->activity->causer_id,
]));
}
} catch (Throwable $e) {
} catch (\Throwable $e) {
Log::error('Error calling event: '.$e->getMessage());
}
}

View File

@@ -16,9 +16,9 @@ class StartClickhouse
public string $configuration_dir;
public function handle(StandaloneClickhouse $standaloneClickhouse)
public function handle(StandaloneClickhouse $database)
{
$this->database = $standaloneClickhouse;
$this->database = $database;
$container_name = $this->database->uuid;
$this->configuration_dir = database_configuration_dir().'/'.$container_name;
@@ -103,12 +103,12 @@ class StartClickhouse
$this->commands[] = "echo '{$docker_compose_base64}' | base64 -d | tee $this->configuration_dir/docker-compose.yml > /dev/null";
$readme = generate_readme_file($this->database->name, now());
$this->commands[] = "echo '{$readme}' > $this->configuration_dir/README.md";
$this->commands[] = "echo 'Pulling {$standaloneClickhouse->image} image.'";
$this->commands[] = "echo 'Pulling {$database->image} image.'";
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull";
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d";
$this->commands[] = "echo 'Database started.'";
return remote_process($this->commands, $standaloneClickhouse->destination->server, callEventOnFinish: 'DatabaseStatusChanged');
return remote_process($this->commands, $database->destination->server, callEventOnFinish: 'DatabaseStatusChanged');
}
private function generate_local_persistent_volumes()

View File

@@ -25,28 +25,28 @@ class StartDatabase
return 'Server is not functional';
}
switch ($database->getMorphClass()) {
case StandalonePostgresql::class:
case \App\Models\StandalonePostgresql::class:
$activity = StartPostgresql::run($database);
break;
case StandaloneRedis::class:
case \App\Models\StandaloneRedis::class:
$activity = StartRedis::run($database);
break;
case StandaloneMongodb::class:
case \App\Models\StandaloneMongodb::class:
$activity = StartMongodb::run($database);
break;
case StandaloneMysql::class:
case \App\Models\StandaloneMysql::class:
$activity = StartMysql::run($database);
break;
case StandaloneMariadb::class:
case \App\Models\StandaloneMariadb::class:
$activity = StartMariadb::run($database);
break;
case StandaloneKeydb::class:
case \App\Models\StandaloneKeydb::class:
$activity = StartKeydb::run($database);
break;
case StandaloneDragonfly::class:
case \App\Models\StandaloneDragonfly::class:
$activity = StartDragonfly::run($database);
break;
case StandaloneClickhouse::class:
case \App\Models\StandaloneClickhouse::class:
$activity = StartClickhouse::run($database);
break;
}

View File

@@ -28,7 +28,7 @@ class StartDatabaseProxy
$server = data_get($database, 'destination.server');
$containerName = data_get($database, 'uuid');
$proxyContainerName = "{$database->uuid}-proxy";
if ($database->getMorphClass() === ServiceDatabase::class) {
if ($database->getMorphClass() === \App\Models\ServiceDatabase::class) {
$databaseType = $database->databaseType();
// $connectPredefined = data_get($database, 'service.connect_to_docker_network');
$network = $database->service->uuid;
@@ -36,54 +36,54 @@ class StartDatabaseProxy
$proxyContainerName = "{$database->service->uuid}-proxy";
switch ($databaseType) {
case 'standalone-mariadb':
$type = StandaloneMariadb::class;
$type = \App\Models\StandaloneMariadb::class;
$containerName = "mariadb-{$database->service->uuid}";
break;
case 'standalone-mongodb':
$type = StandaloneMongodb::class;
$type = \App\Models\StandaloneMongodb::class;
$containerName = "mongodb-{$database->service->uuid}";
break;
case 'standalone-mysql':
$type = StandaloneMysql::class;
$type = \App\Models\StandaloneMysql::class;
$containerName = "mysql-{$database->service->uuid}";
break;
case 'standalone-postgresql':
$type = StandalonePostgresql::class;
$type = \App\Models\StandalonePostgresql::class;
$containerName = "postgresql-{$database->service->uuid}";
break;
case 'standalone-redis':
$type = StandaloneRedis::class;
$type = \App\Models\StandaloneRedis::class;
$containerName = "redis-{$database->service->uuid}";
break;
case 'standalone-keydb':
$type = StandaloneKeydb::class;
$type = \App\Models\StandaloneKeydb::class;
$containerName = "keydb-{$database->service->uuid}";
break;
case 'standalone-dragonfly':
$type = StandaloneDragonfly::class;
$type = \App\Models\StandaloneDragonfly::class;
$containerName = "dragonfly-{$database->service->uuid}";
break;
case 'standalone-clickhouse':
$type = StandaloneClickhouse::class;
$type = \App\Models\StandaloneClickhouse::class;
$containerName = "clickhouse-{$database->service->uuid}";
break;
}
}
if ($type === StandaloneRedis::class) {
if ($type === \App\Models\StandaloneRedis::class) {
$internalPort = 6379;
} elseif ($type === StandalonePostgresql::class) {
} elseif ($type === \App\Models\StandalonePostgresql::class) {
$internalPort = 5432;
} elseif ($type === StandaloneMongodb::class) {
} elseif ($type === \App\Models\StandaloneMongodb::class) {
$internalPort = 27017;
} elseif ($type === StandaloneMysql::class) {
} elseif ($type === \App\Models\StandaloneMysql::class) {
$internalPort = 3306;
} elseif ($type === StandaloneMariadb::class) {
} elseif ($type === \App\Models\StandaloneMariadb::class) {
$internalPort = 3306;
} elseif ($type === StandaloneKeydb::class) {
} elseif ($type === \App\Models\StandaloneKeydb::class) {
$internalPort = 6379;
} elseif ($type === StandaloneDragonfly::class) {
} elseif ($type === \App\Models\StandaloneDragonfly::class) {
$internalPort = 6379;
} elseif ($type === StandaloneClickhouse::class) {
} elseif ($type === \App\Models\StandaloneClickhouse::class) {
$internalPort = 9000;
}
$configuration_dir = database_proxy_dir($database->uuid);

View File

@@ -16,9 +16,9 @@ class StartDragonfly
public string $configuration_dir;
public function handle(StandaloneDragonfly $standaloneDragonfly)
public function handle(StandaloneDragonfly $database)
{
$this->database = $standaloneDragonfly;
$this->database = $database;
$startCommand = "dragonfly --requirepass {$this->database->dragonfly_password}";
@@ -100,12 +100,12 @@ class StartDragonfly
$this->commands[] = "echo '{$docker_compose_base64}' | base64 -d | tee $this->configuration_dir/docker-compose.yml > /dev/null";
$readme = generate_readme_file($this->database->name, now());
$this->commands[] = "echo '{$readme}' > $this->configuration_dir/README.md";
$this->commands[] = "echo 'Pulling {$standaloneDragonfly->image} image.'";
$this->commands[] = "echo 'Pulling {$database->image} image.'";
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull";
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d";
$this->commands[] = "echo 'Database started.'";
return remote_process($this->commands, $standaloneDragonfly->destination->server, callEventOnFinish: 'DatabaseStatusChanged');
return remote_process($this->commands, $database->destination->server, callEventOnFinish: 'DatabaseStatusChanged');
}
private function generate_local_persistent_volumes()

View File

@@ -17,9 +17,9 @@ class StartKeydb
public string $configuration_dir;
public function handle(StandaloneKeydb $standaloneKeydb)
public function handle(StandaloneKeydb $database)
{
$this->database = $standaloneKeydb;
$this->database = $database;
$startCommand = "keydb-server --requirepass {$this->database->keydb_password} --appendonly yes";
@@ -92,7 +92,7 @@ class StartKeydb
if (count($volume_names) > 0) {
$docker_compose['volumes'] = $volume_names;
}
if (! is_null($this->database->keydb_conf) || $this->database->keydb_conf !== null) {
if (! is_null($this->database->keydb_conf) || ! empty($this->database->keydb_conf)) {
$docker_compose['services'][$container_name]['volumes'][] = [
'type' => 'bind',
'source' => $this->configuration_dir.'/keydb.conf',
@@ -110,12 +110,12 @@ class StartKeydb
$this->commands[] = "echo '{$docker_compose_base64}' | base64 -d | tee $this->configuration_dir/docker-compose.yml > /dev/null";
$readme = generate_readme_file($this->database->name, now());
$this->commands[] = "echo '{$readme}' > $this->configuration_dir/README.md";
$this->commands[] = "echo 'Pulling {$standaloneKeydb->image} image.'";
$this->commands[] = "echo 'Pulling {$database->image} image.'";
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull";
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d";
$this->commands[] = "echo 'Database started.'";
return remote_process($this->commands, $standaloneKeydb->destination->server, callEventOnFinish: 'DatabaseStatusChanged');
return remote_process($this->commands, $database->destination->server, callEventOnFinish: 'DatabaseStatusChanged');
}
private function generate_local_persistent_volumes()

View File

@@ -16,9 +16,9 @@ class StartMariadb
public string $configuration_dir;
public function handle(StandaloneMariadb $standaloneMariadb)
public function handle(StandaloneMariadb $database)
{
$this->database = $standaloneMariadb;
$this->database = $database;
$container_name = $this->database->uuid;
$this->configuration_dir = database_configuration_dir().'/'.$container_name;
@@ -87,7 +87,7 @@ class StartMariadb
if (count($volume_names) > 0) {
$docker_compose['volumes'] = $volume_names;
}
if (! is_null($this->database->mariadb_conf) || $this->database->mariadb_conf !== null) {
if (! is_null($this->database->mariadb_conf) || ! empty($this->database->mariadb_conf)) {
$docker_compose['services'][$container_name]['volumes'][] = [
'type' => 'bind',
'source' => $this->configuration_dir.'/custom-config.cnf',
@@ -105,12 +105,12 @@ class StartMariadb
$this->commands[] = "echo '{$docker_compose_base64}' | base64 -d | tee $this->configuration_dir/docker-compose.yml > /dev/null";
$readme = generate_readme_file($this->database->name, now());
$this->commands[] = "echo '{$readme}' > $this->configuration_dir/README.md";
$this->commands[] = "echo 'Pulling {$standaloneMariadb->image} image.'";
$this->commands[] = "echo 'Pulling {$database->image} image.'";
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull";
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d";
$this->commands[] = "echo 'Database started.'";
return remote_process($this->commands, $standaloneMariadb->destination->server, callEventOnFinish: 'DatabaseStatusChanged');
return remote_process($this->commands, $database->destination->server, callEventOnFinish: 'DatabaseStatusChanged');
}
private function generate_local_persistent_volumes()

View File

@@ -16,9 +16,9 @@ class StartMongodb
public string $configuration_dir;
public function handle(StandaloneMongodb $standaloneMongodb)
public function handle(StandaloneMongodb $database)
{
$this->database = $standaloneMongodb;
$this->database = $database;
$startCommand = 'mongod';
@@ -99,7 +99,7 @@ class StartMongodb
if (count($volume_names) > 0) {
$docker_compose['volumes'] = $volume_names;
}
if (! is_null($this->database->mongo_conf) || $this->database->mongo_conf !== null) {
if (! is_null($this->database->mongo_conf) || ! empty($this->database->mongo_conf)) {
$docker_compose['services'][$container_name]['volumes'][] = [
'type' => 'bind',
'source' => $this->configuration_dir.'/mongod.conf',
@@ -125,12 +125,12 @@ class StartMongodb
$this->commands[] = "echo '{$docker_compose_base64}' | base64 -d | tee $this->configuration_dir/docker-compose.yml > /dev/null";
$readme = generate_readme_file($this->database->name, now());
$this->commands[] = "echo '{$readme}' > $this->configuration_dir/README.md";
$this->commands[] = "echo 'Pulling {$standaloneMongodb->image} image.'";
$this->commands[] = "echo 'Pulling {$database->image} image.'";
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull";
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d";
$this->commands[] = "echo 'Database started.'";
return remote_process($this->commands, $standaloneMongodb->destination->server, callEventOnFinish: 'DatabaseStatusChanged');
return remote_process($this->commands, $database->destination->server, callEventOnFinish: 'DatabaseStatusChanged');
}
private function generate_local_persistent_volumes()

View File

@@ -16,9 +16,9 @@ class StartMysql
public string $configuration_dir;
public function handle(StandaloneMysql $standaloneMysql)
public function handle(StandaloneMysql $database)
{
$this->database = $standaloneMysql;
$this->database = $database;
$container_name = $this->database->uuid;
$this->configuration_dir = database_configuration_dir().'/'.$container_name;
@@ -87,7 +87,7 @@ class StartMysql
if (count($volume_names) > 0) {
$docker_compose['volumes'] = $volume_names;
}
if (! is_null($this->database->mysql_conf) || $this->database->mysql_conf !== null) {
if (! is_null($this->database->mysql_conf) || ! empty($this->database->mysql_conf)) {
$docker_compose['services'][$container_name]['volumes'][] = [
'type' => 'bind',
'source' => $this->configuration_dir.'/custom-config.cnf',
@@ -105,12 +105,12 @@ class StartMysql
$this->commands[] = "echo '{$docker_compose_base64}' | base64 -d | tee $this->configuration_dir/docker-compose.yml > /dev/null";
$readme = generate_readme_file($this->database->name, now());
$this->commands[] = "echo '{$readme}' > $this->configuration_dir/README.md";
$this->commands[] = "echo 'Pulling {$standaloneMysql->image} image.'";
$this->commands[] = "echo 'Pulling {$database->image} image.'";
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull";
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d";
$this->commands[] = "echo 'Database started.'";
return remote_process($this->commands, $standaloneMysql->destination->server, callEventOnFinish: 'DatabaseStatusChanged');
return remote_process($this->commands, $database->destination->server, callEventOnFinish: 'DatabaseStatusChanged');
}
private function generate_local_persistent_volumes()

View File

@@ -18,9 +18,9 @@ class StartPostgresql
public string $configuration_dir;
public function handle(StandalonePostgresql $standalonePostgresql)
public function handle(StandalonePostgresql $database)
{
$this->database = $standalonePostgresql;
$this->database = $database;
$container_name = $this->database->uuid;
$this->configuration_dir = database_configuration_dir().'/'.$container_name;
if (isDev()) {
@@ -97,13 +97,15 @@ class StartPostgresql
if (count($volume_names) > 0) {
$docker_compose['volumes'] = $volume_names;
}
foreach ($this->init_scripts as $init_script) {
$docker_compose['services'][$container_name]['volumes'][] = [
'type' => 'bind',
'source' => $init_script,
'target' => '/docker-entrypoint-initdb.d/'.basename($init_script),
'read_only' => true,
];
if (count($this->init_scripts) > 0) {
foreach ($this->init_scripts as $init_script) {
$docker_compose['services'][$container_name]['volumes'][] = [
'type' => 'bind',
'source' => $init_script,
'target' => '/docker-entrypoint-initdb.d/'.basename($init_script),
'read_only' => true,
];
}
}
if (filled($this->database->postgres_conf)) {
$docker_compose['services'][$container_name]['volumes'][] = [
@@ -127,12 +129,12 @@ class StartPostgresql
$this->commands[] = "echo '{$docker_compose_base64}' | base64 -d | tee $this->configuration_dir/docker-compose.yml > /dev/null";
$readme = generate_readme_file($this->database->name, now());
$this->commands[] = "echo '{$readme}' > $this->configuration_dir/README.md";
$this->commands[] = "echo 'Pulling {$standalonePostgresql->image} image.'";
$this->commands[] = "echo 'Pulling {$database->image} image.'";
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull";
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d";
$this->commands[] = "echo 'Database started.'";
return remote_process($this->commands, $standalonePostgresql->destination->server, callEventOnFinish: 'DatabaseStatusChanged');
return remote_process($this->commands, $database->destination->server, callEventOnFinish: 'DatabaseStatusChanged');
}
private function generate_local_persistent_volumes()

View File

@@ -17,9 +17,9 @@ class StartRedis
public string $configuration_dir;
public function handle(StandaloneRedis $standaloneRedis)
public function handle(StandaloneRedis $database)
{
$this->database = $standaloneRedis;
$this->database = $database;
$container_name = $this->database->uuid;
$this->configuration_dir = database_configuration_dir().'/'.$container_name;
@@ -96,7 +96,7 @@ class StartRedis
if (count($volume_names) > 0) {
$docker_compose['volumes'] = $volume_names;
}
if (! is_null($this->database->redis_conf) || $this->database->redis_conf !== null) {
if (! is_null($this->database->redis_conf) || ! empty($this->database->redis_conf)) {
$docker_compose['services'][$container_name]['volumes'][] = [
'type' => 'bind',
'source' => $this->configuration_dir.'/redis.conf',
@@ -114,12 +114,12 @@ class StartRedis
$this->commands[] = "echo '{$docker_compose_base64}' | base64 -d | tee $this->configuration_dir/docker-compose.yml > /dev/null";
$readme = generate_readme_file($this->database->name, now());
$this->commands[] = "echo '{$readme}' > $this->configuration_dir/README.md";
$this->commands[] = "echo 'Pulling {$standaloneRedis->image} image.'";
$this->commands[] = "echo 'Pulling {$database->image} image.'";
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull";
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d";
$this->commands[] = "echo 'Database started.'";
return remote_process($this->commands, $standaloneRedis->destination->server, callEventOnFinish: 'DatabaseStatusChanged');
return remote_process($this->commands, $database->destination->server, callEventOnFinish: 'DatabaseStatusChanged');
}
private function generate_local_persistent_volumes()

View File

@@ -26,8 +26,10 @@ class StopDatabase
}
$this->stopContainer($database, $database->uuid, 300);
if (! $isDeleteOperation && $dockerCleanup) {
CleanupDocker::dispatch($server, true);
if (! $isDeleteOperation) {
if ($dockerCleanup) {
CleanupDocker::dispatch($server, true);
}
}
if ($database->is_public) {
@@ -41,10 +43,10 @@ class StopDatabase
{
$server = $database->destination->server;
$invokedProcess = Process::timeout($timeout)->start("docker stop --time=$timeout $containerName");
$process = Process::timeout($timeout)->start("docker stop --time=$timeout $containerName");
$startTime = time();
while ($invokedProcess->running()) {
while ($process->running()) {
if (time() - $startTime >= $timeout) {
$this->forceStopContainer($containerName, $server);
break;
@@ -64,4 +66,10 @@ class StopDatabase
{
instant_remote_process(command: ["docker rm -f $containerName"], server: $server, throwError: false);
}
private function deleteConnectedNetworks($uuid, $server)
{
instant_remote_process(["docker network disconnect {$uuid} coolify-proxy"], $server, false);
instant_remote_process(["docker network rm {$uuid}"], $server, false);
}
}

View File

@@ -24,7 +24,7 @@ class StopDatabaseProxy
{
$server = data_get($database, 'destination.server');
$uuid = $database->uuid;
if ($database->getMorphClass() === ServiceDatabase::class) {
if ($database->getMorphClass() === \App\Models\ServiceDatabase::class) {
$uuid = $database->service->uuid;
$server = data_get($database, 'service.server');
}

View File

@@ -47,20 +47,20 @@ class GetContainersStatus
$this->applications = $this->applications->filter(function ($value, $key) use ($skip_these_applications) {
return ! $skip_these_applications->pluck('id')->contains($value->id);
});
if (! $this->containers instanceof Collection) {
if ($this->containers === null) {
['containers' => $this->containers, 'containerReplicates' => $this->containerReplicates] = $this->server->getContainers();
}
if (is_null($this->containers)) {
return null;
return;
}
if ($this->containerReplicates) {
foreach ($this->containerReplicates as $containerReplicate) {
$name = data_get($containerReplicate, 'Name');
$this->containers = $this->containers->map(function ($container) use ($name, $containerReplicate) {
foreach ($this->containerReplicates as $containerReplica) {
$name = data_get($containerReplica, 'Name');
$this->containers = $this->containers->map(function ($container) use ($name, $containerReplica) {
if (data_get($container, 'Spec.Name') === $name) {
$replicas = data_get($containerReplicate, 'Replicas');
$replicas = data_get($containerReplica, 'Replicas');
$running = str($replicas)->explode('/')[0];
$total = str($replicas)->explode('/')[1];
if ($running === $total) {
@@ -102,7 +102,7 @@ class GetContainersStatus
if (str($applicationId)->contains('-')) {
$applicationId = str($applicationId)->before('-');
}
$preview = ApplicationPreview::query()->where('application_id', $applicationId)->where('pull_request_id', $pullRequestId)->first();
$preview = ApplicationPreview::where('application_id', $applicationId)->where('pull_request_id', $pullRequestId)->first();
if ($preview) {
$foundApplicationPreviews[] = $preview->id;
$statusFromDb = $preview->status;
@@ -136,7 +136,7 @@ class GetContainersStatus
if ($type === 'service') {
$database_id = data_get($labels, 'coolify.service.subId');
if ($database_id) {
$service_db = ServiceDatabase::query()->where('id', $database_id)->first();
$service_db = ServiceDatabase::where('id', $database_id)->first();
if ($service_db) {
$uuid = data_get($service_db, 'service.uuid');
if ($uuid) {
@@ -145,9 +145,9 @@ class GetContainersStatus
$foundTcpProxy = $this->containers->filter(function ($value, $key) use ($uuid) {
if ($this->server->isSwarm()) {
return data_get($value, 'Spec.Name') === "coolify-proxy_$uuid";
} else {
return data_get($value, 'Name') === "/$uuid-proxy";
}
return data_get($value, 'Name') === "/$uuid-proxy";
})->first();
if (! $foundTcpProxy) {
StartDatabaseProxy::run($service_db);
@@ -173,9 +173,9 @@ class GetContainersStatus
$foundTcpProxy = $this->containers->filter(function ($value, $key) use ($uuid) {
if ($this->server->isSwarm()) {
return data_get($value, 'Spec.Name') === "coolify-proxy_$uuid";
} else {
return data_get($value, 'Name') === "/$uuid-proxy";
}
return data_get($value, 'Name') === "/$uuid-proxy";
})->first();
if (! $foundTcpProxy) {
StartDatabaseProxy::run($database);
@@ -223,14 +223,16 @@ class GetContainersStatus
foreach ($apps as $app) {
if (in_array("$app->id-$app->name", $foundServices)) {
continue;
} else {
$exitedServices->push($app);
}
$exitedServices->push($app);
}
foreach ($dbs as $db) {
if (in_array("$db->id-$db->name", $foundServices)) {
continue;
} else {
$exitedServices->push($db);
}
$exitedServices->push($db);
}
}
$exitedServices = $exitedServices->unique('uuid');
@@ -241,11 +243,17 @@ class GetContainersStatus
$name = data_get($exitedService, 'name');
$fqdn = data_get($exitedService, 'fqdn');
if ($name) {
$containerName = $fqdn ? "$name, available at $fqdn" : $name;
} elseif ($fqdn) {
$containerName = $fqdn;
if ($fqdn) {
$containerName = "$name, available at $fqdn";
} else {
$containerName = $name;
}
} else {
$containerName = null;
if ($fqdn) {
$containerName = $fqdn;
} else {
$containerName = null;
}
}
$projectUuid = data_get($service, 'environment.project.uuid');
$serviceUuid = data_get($service, 'uuid');
@@ -261,8 +269,8 @@ class GetContainersStatus
}
$notRunningApplications = $this->applications->pluck('id')->diff($foundApplications);
foreach ($notRunningApplications as $notRunningApplication) {
$application = $this->applications->where('id', $notRunningApplication)->first();
foreach ($notRunningApplications as $applicationId) {
$application = $this->applications->where('id', $applicationId)->first();
if (str($application->status)->startsWith('exited')) {
continue;
}
@@ -286,8 +294,8 @@ class GetContainersStatus
// $this->server->team?->notify(new ContainerStopped($containerName, $this->server, $url));
}
$notRunningApplicationPreviews = $previews->pluck('id')->diff($foundApplicationPreviews);
foreach ($notRunningApplicationPreviews as $notRunningApplicationPreview) {
$preview = $previews->where('id', $notRunningApplicationPreview)->first();
foreach ($notRunningApplicationPreviews as $previewId) {
$preview = $previews->where('id', $previewId)->first();
if (str($preview->status)->startsWith('exited')) {
continue;
}
@@ -311,21 +319,21 @@ class GetContainersStatus
// $this->server->team?->notify(new ContainerStopped($containerName, $this->server, $url));
}
$notRunningDatabases = $databases->pluck('id')->diff($foundDatabases);
foreach ($notRunningDatabases as $notRunningDatabase) {
$notRunningDatabase = $databases->where('id', $notRunningDatabase)->first();
if (str($notRunningDatabase->status)->startsWith('exited')) {
foreach ($notRunningDatabases as $database) {
$database = $databases->where('id', $database)->first();
if (str($database->status)->startsWith('exited')) {
continue;
}
$notRunningDatabase->update(['status' => 'exited']);
$database->update(['status' => 'exited']);
$name = data_get($notRunningDatabase, 'name');
$fqdn = data_get($notRunningDatabase, 'fqdn');
$name = data_get($database, 'name');
$fqdn = data_get($database, 'fqdn');
$containerName = $name;
$projectUuid = data_get($notRunningDatabase, 'environment.project.uuid');
$environmentName = data_get($notRunningDatabase, 'environment.name');
$databaseUuid = data_get($notRunningDatabase, 'uuid');
$projectUuid = data_get($database, 'environment.project.uuid');
$environmentName = data_get($database, 'environment.name');
$databaseUuid = data_get($database, 'uuid');
if ($projectUuid && $databaseUuid && $environmentName) {
$url = base_url().'/project/'.$projectUuid.'/'.$environmentName.'/database/'.$databaseUuid;
@@ -334,7 +342,5 @@ class GetContainersStatus
}
// $this->server->team?->notify(new ContainerStopped($containerName, $this->server, $url));
}
return null;
}
}

View File

@@ -34,10 +34,10 @@ class CreateNewUser implements CreatesNewUsers
'password' => ['required', Password::defaults(), 'confirmed'],
])->validate();
if (User::query()->count() == 0) {
if (User::count() == 0) {
// If this is the first user, make them the root user
// Team is already created in the database/seeders/ProductionSeeder.php
$user = User::query()->create([
$user = User::create([
'id' => 0,
'name' => $input['name'],
'email' => strtolower($input['email']),
@@ -50,7 +50,7 @@ class CreateNewUser implements CreatesNewUsers
$settings->is_registration_enabled = false;
$settings->save();
} else {
$user = User::query()->create([
$user = User::create([
'name' => $input['name'],
'email' => strtolower($input['email']),
'password' => Hash::make($input['password']),

View File

@@ -3,7 +3,6 @@
namespace App\Actions\Proxy;
use App\Models\Server;
use Exception;
use Lorisleiva\Actions\Concerns\AsAction;
class CheckConfiguration
@@ -26,7 +25,7 @@ class CheckConfiguration
$proxy_configuration = str(generate_default_proxy_configuration($server))->trim()->value();
}
if (! $proxy_configuration || is_null($proxy_configuration)) {
throw new Exception('Could not generate proxy configuration');
throw new \Exception('Could not generate proxy configuration');
}
return $proxy_configuration;

View File

@@ -4,7 +4,6 @@ namespace App\Actions\Proxy;
use App\Enums\ProxyTypes;
use App\Models\Server;
use Exception;
use Illuminate\Support\Facades\Log;
use Lorisleiva\Actions\Concerns\AsAction;
use Symfony\Component\Yaml\Yaml;
@@ -33,74 +32,80 @@ class CheckProxy
}
['uptime' => $uptime, 'error' => $error] = $server->validateConnection();
if (! $uptime) {
throw new Exception($error);
throw new \Exception($error);
}
if (! $server->isProxyShouldRun()) {
if ($fromUI) {
throw new Exception('Proxy should not run. You selected the Custom Proxy.');
throw new \Exception('Proxy should not run. You selected the Custom Proxy.');
} else {
return false;
}
return false;
}
if ($server->isSwarm()) {
$status = getContainerStatus($server, 'coolify-proxy_traefik');
$server->proxy->set('status', $status);
$server->save();
return $status !== 'running';
}
$status = getContainerStatus($server, 'coolify-proxy');
if ($status === 'running') {
$server->proxy->set('status', 'running');
$server->save();
return false;
}
if ($server->settings->is_cloudflare_tunnel) {
return false;
}
$ip = $server->ip;
if ($server->id === 0) {
$ip = 'host.docker.internal';
}
$portsToCheck = ['80', '443'];
try {
if ($server->proxyType() !== ProxyTypes::NONE->value) {
$proxyCompose = CheckConfiguration::run($server);
if (isset($proxyCompose)) {
$yaml = Yaml::parse($proxyCompose);
$portsToCheck = [];
if ($server->proxyType() === ProxyTypes::TRAEFIK->value) {
$ports = data_get($yaml, 'services.traefik.ports');
} elseif ($server->proxyType() === ProxyTypes::CADDY->value) {
$ports = data_get($yaml, 'services.caddy.ports');
}
if (isset($ports)) {
foreach ($ports as $port) {
$portsToCheck[] = str($port)->before(':')->value();
}
}
}
} else {
$portsToCheck = [];
if ($status === 'running') {
return false;
}
} catch (Exception $e) {
Log::error('Error checking proxy: '.$e->getMessage());
}
if ($portsToCheck === []) {
return false;
}
foreach ($portsToCheck as $portToCheck) {
$connection = @fsockopen($ip, $portToCheck);
if (is_resource($connection) && fclose($connection)) {
if ($fromUI) {
throw new Exception("Port {$portToCheck} is in use.<br>You must stop the process using this port.<br>Docs: <a target='_blank' href='https://coolify.io/docs'>https://coolify.io/docs</a><br>Discord: <a target='_blank' href='https://coollabs.io/discord'>https://coollabs.io/discord</a>");
}
return true;
} else {
$status = getContainerStatus($server, 'coolify-proxy');
if ($status === 'running') {
$server->proxy->set('status', 'running');
$server->save();
return false;
}
}
if ($server->settings->is_cloudflare_tunnel) {
return false;
}
$ip = $server->ip;
if ($server->id === 0) {
$ip = 'host.docker.internal';
}
return true;
$portsToCheck = ['80', '443'];
try {
if ($server->proxyType() !== ProxyTypes::NONE->value) {
$proxyCompose = CheckConfiguration::run($server);
if (isset($proxyCompose)) {
$yaml = Yaml::parse($proxyCompose);
$portsToCheck = [];
if ($server->proxyType() === ProxyTypes::TRAEFIK->value) {
$ports = data_get($yaml, 'services.traefik.ports');
} elseif ($server->proxyType() === ProxyTypes::CADDY->value) {
$ports = data_get($yaml, 'services.caddy.ports');
}
if (isset($ports)) {
foreach ($ports as $port) {
$portsToCheck[] = str($port)->before(':')->value();
}
}
}
} else {
$portsToCheck = [];
}
} catch (\Exception $e) {
Log::error('Error checking proxy: '.$e->getMessage());
}
if (count($portsToCheck) === 0) {
return false;
}
foreach ($portsToCheck as $port) {
$connection = @fsockopen($ip, $port);
if (is_resource($connection) && fclose($connection)) {
if ($fromUI) {
throw new \Exception("Port $port is in use.<br>You must stop the process using this port.<br>Docs: <a target='_blank' href='https://coolify.io/docs'>https://coolify.io/docs</a><br>Discord: <a target='_blank' href='https://coollabs.io/discord'>https://coollabs.io/discord</a>");
} else {
return false;
}
}
}
return true;
}
}
}

View File

@@ -5,7 +5,6 @@ namespace App\Actions\Proxy;
use App\Enums\ProxyTypes;
use App\Events\ProxyStarted;
use App\Models\Server;
use Exception;
use Lorisleiva\Actions\Concerns\AsAction;
use Spatie\Activitylog\Models\Activity;
@@ -23,7 +22,7 @@ class StartProxy
$proxy_path = $server->proxyPath();
$configuration = CheckConfiguration::run($server);
if (! $configuration) {
throw new Exception('Configuration is not synced');
throw new \Exception('Configuration is not synced');
}
SaveConfiguration::run($server, $configuration);
$docker_compose_yml_base64 = base64_encode($configuration);
@@ -39,8 +38,10 @@ class StartProxy
"echo 'Successfully started coolify-proxy.'",
]);
} else {
if (isDev() && $proxyType === ProxyTypes::CADDY->value) {
$proxy_path = '/data/coolify/proxy/caddy';
if (isDev()) {
if ($proxyType === ProxyTypes::CADDY->value) {
$proxy_path = '/data/coolify/proxy/caddy';
}
}
$caddyfile = 'import /dynamic/*.caddy';
$commands = $commands->merge([
@@ -64,13 +65,14 @@ class StartProxy
if ($async) {
return remote_process($commands, $server, callEventOnFinish: 'ProxyStarted', callEventData: $server);
}
instant_remote_process($commands, $server);
$server->proxy->set('status', 'running');
$server->proxy->set('type', $proxyType);
$server->save();
ProxyStarted::dispatch($server);
} else {
instant_remote_process($commands, $server);
$server->proxy->set('status', 'running');
$server->proxy->set('type', $proxyType);
$server->save();
ProxyStarted::dispatch($server);
return 'OK';
return 'OK';
}
}
}

View File

@@ -6,7 +6,6 @@ use App\Events\CloudflareTunnelConfigured;
use App\Models\Server;
use Lorisleiva\Actions\Concerns\AsAction;
use Symfony\Component\Yaml\Yaml;
use Throwable;
class ConfigureCloudflared
{
@@ -40,7 +39,7 @@ class ConfigureCloudflared
'docker compose up -d --remove-orphans',
]);
instant_remote_process($commands, $server);
} catch (Throwable $e) {
} catch (\Throwable $e) {
$server->settings->is_cloudflare_tunnel = false;
$server->settings->save();
throw $e;

View File

@@ -4,7 +4,6 @@ namespace App\Actions\Server;
use App\Models\Server;
use App\Models\StandaloneDocker;
use Exception;
use Lorisleiva\Actions\Concerns\AsAction;
class InstallDocker
@@ -16,7 +15,7 @@ class InstallDocker
$dockerVersion = config('constants.docker.minimum_required_version');
$supported_os_type = $server->validateOS();
if (! $supported_os_type) {
throw new Exception('Server OS type is not supported for automated installation. Please install Docker manually before continuing: <a target="_blank" class="underline" href="https://coolify.io/docs/installation#manually">documentation</a>.');
throw new \Exception('Server OS type is not supported for automated installation. Please install Docker manually before continuing: <a target="_blank" class="underline" href="https://coolify.io/docs/installation#manually">documentation</a>.');
}
$config = base64_encode('{
"log-driver": "json-file",
@@ -25,9 +24,9 @@ class InstallDocker
"max-file": "3"
}
}');
$builder = StandaloneDocker::query()->where('server_id', $server->id);
if ($builder->count() == 0 && $server->id) {
StandaloneDocker::query()->create([
$found = StandaloneDocker::where('server_id', $server->id);
if ($found->count() == 0 && $server->id) {
StandaloneDocker::create([
'name' => 'coolify',
'network' => 'coolify',
'server_id' => $server->id,
@@ -46,64 +45,65 @@ class InstallDocker
]);
return remote_process($command, $server);
}
if ($supported_os_type->contains('debian')) {
$command = $command->merge([
"echo 'Installing Prerequisites...'",
'apt-get update -y',
'command -v curl >/dev/null || apt install -y curl',
'command -v wget >/dev/null || apt install -y wget',
'command -v git >/dev/null || apt install -y git',
'command -v jq >/dev/null || apt install -y jq',
]);
} elseif ($supported_os_type->contains('rhel')) {
$command = $command->merge([
"echo 'Installing Prerequisites...'",
'command -v curl >/dev/null || dnf install -y curl',
'command -v wget >/dev/null || dnf install -y wget',
'command -v git >/dev/null || dnf install -y git',
'command -v jq >/dev/null || dnf install -y jq',
]);
} elseif ($supported_os_type->contains('sles')) {
$command = $command->merge([
"echo 'Installing Prerequisites...'",
'zypper update -y',
'command -v curl >/dev/null || zypper install -y curl',
'command -v wget >/dev/null || zypper install -y wget',
'command -v git >/dev/null || zypper install -y git',
'command -v jq >/dev/null || zypper install -y jq',
]);
} else {
throw new Exception('Unsupported OS');
}
$command = $command->merge([
"echo 'Installing Docker Engine...'",
"curl https://releases.rancher.com/install-docker/{$dockerVersion}.sh | sh || curl https://get.docker.com | sh -s -- --version {$dockerVersion}",
"echo 'Configuring Docker Engine (merging existing configuration with the required)...'",
'test -s /etc/docker/daemon.json && cp /etc/docker/daemon.json "/etc/docker/daemon.json.original-$(date +"%Y%m%d-%H%M%S")"',
"test ! -s /etc/docker/daemon.json && echo '{$config}' | base64 -d | tee /etc/docker/daemon.json > /dev/null",
"echo '{$config}' | base64 -d | tee /etc/docker/daemon.json.coolify > /dev/null",
'jq . /etc/docker/daemon.json.coolify | tee /etc/docker/daemon.json.coolify.pretty > /dev/null',
'mv /etc/docker/daemon.json.coolify.pretty /etc/docker/daemon.json.coolify',
"jq -s '.[0] * .[1]' /etc/docker/daemon.json.coolify /etc/docker/daemon.json | tee /etc/docker/daemon.json.appended > /dev/null",
'mv /etc/docker/daemon.json.appended /etc/docker/daemon.json',
"echo 'Restarting Docker Engine...'",
'systemctl enable docker >/dev/null 2>&1 || true',
'systemctl restart docker',
]);
if ($server->isSwarm()) {
if ($supported_os_type->contains('debian')) {
$command = $command->merge([
"echo 'Installing Prerequisites...'",
'apt-get update -y',
'command -v curl >/dev/null || apt install -y curl',
'command -v wget >/dev/null || apt install -y wget',
'command -v git >/dev/null || apt install -y git',
'command -v jq >/dev/null || apt install -y jq',
]);
} elseif ($supported_os_type->contains('rhel')) {
$command = $command->merge([
"echo 'Installing Prerequisites...'",
'command -v curl >/dev/null || dnf install -y curl',
'command -v wget >/dev/null || dnf install -y wget',
'command -v git >/dev/null || dnf install -y git',
'command -v jq >/dev/null || dnf install -y jq',
]);
} elseif ($supported_os_type->contains('sles')) {
$command = $command->merge([
"echo 'Installing Prerequisites...'",
'zypper update -y',
'command -v curl >/dev/null || zypper install -y curl',
'command -v wget >/dev/null || zypper install -y wget',
'command -v git >/dev/null || zypper install -y git',
'command -v jq >/dev/null || zypper install -y jq',
]);
} else {
throw new \Exception('Unsupported OS');
}
$command = $command->merge([
'docker network create --attachable --driver overlay coolify-overlay >/dev/null 2>&1 || true',
"echo 'Installing Docker Engine...'",
"curl https://releases.rancher.com/install-docker/{$dockerVersion}.sh | sh || curl https://get.docker.com | sh -s -- --version {$dockerVersion}",
"echo 'Configuring Docker Engine (merging existing configuration with the required)...'",
'test -s /etc/docker/daemon.json && cp /etc/docker/daemon.json "/etc/docker/daemon.json.original-$(date +"%Y%m%d-%H%M%S")"',
"test ! -s /etc/docker/daemon.json && echo '{$config}' | base64 -d | tee /etc/docker/daemon.json > /dev/null",
"echo '{$config}' | base64 -d | tee /etc/docker/daemon.json.coolify > /dev/null",
'jq . /etc/docker/daemon.json.coolify | tee /etc/docker/daemon.json.coolify.pretty > /dev/null',
'mv /etc/docker/daemon.json.coolify.pretty /etc/docker/daemon.json.coolify',
"jq -s '.[0] * .[1]' /etc/docker/daemon.json.coolify /etc/docker/daemon.json | tee /etc/docker/daemon.json.appended > /dev/null",
'mv /etc/docker/daemon.json.appended /etc/docker/daemon.json',
"echo 'Restarting Docker Engine...'",
'systemctl enable docker >/dev/null 2>&1 || true',
'systemctl restart docker',
]);
} else {
$command = $command->merge([
'docker network create --attachable coolify >/dev/null 2>&1 || true',
]);
$command = $command->merge([
"echo 'Done!'",
]);
}
if ($server->isSwarm()) {
$command = $command->merge([
'docker network create --attachable --driver overlay coolify-overlay >/dev/null 2>&1 || true',
]);
} else {
$command = $command->merge([
'docker network create --attachable coolify >/dev/null 2>&1 || true',
]);
$command = $command->merge([
"echo 'Done!'",
]);
}
return remote_process($command, $server);
return remote_process($command, $server);
}
}
}

View File

@@ -14,7 +14,6 @@ use App\Models\StandaloneMysql;
use App\Models\StandalonePostgresql;
use App\Models\StandaloneRedis;
use Lorisleiva\Actions\Concerns\AsAction;
use Throwable;
class ResourcesCheck
{
@@ -24,21 +23,19 @@ class ResourcesCheck
{
$seconds = 60;
try {
Application::query()->where('last_online_at', '<', now()->subSeconds($seconds))->update(['status' => 'exited']);
ServiceApplication::query()->where('last_online_at', '<', now()->subSeconds($seconds))->update(['status' => 'exited']);
ServiceDatabase::query()->where('last_online_at', '<', now()->subSeconds($seconds))->update(['status' => 'exited']);
StandalonePostgresql::query()->where('last_online_at', '<', now()->subSeconds($seconds))->update(['status' => 'exited']);
StandaloneRedis::query()->where('last_online_at', '<', now()->subSeconds($seconds))->update(['status' => 'exited']);
StandaloneMongodb::query()->where('last_online_at', '<', now()->subSeconds($seconds))->update(['status' => 'exited']);
StandaloneMysql::query()->where('last_online_at', '<', now()->subSeconds($seconds))->update(['status' => 'exited']);
StandaloneMariadb::query()->where('last_online_at', '<', now()->subSeconds($seconds))->update(['status' => 'exited']);
StandaloneKeydb::query()->where('last_online_at', '<', now()->subSeconds($seconds))->update(['status' => 'exited']);
StandaloneDragonfly::query()->where('last_online_at', '<', now()->subSeconds($seconds))->update(['status' => 'exited']);
StandaloneClickhouse::query()->where('last_online_at', '<', now()->subSeconds($seconds))->update(['status' => 'exited']);
} catch (Throwable $e) {
Application::where('last_online_at', '<', now()->subSeconds($seconds))->update(['status' => 'exited']);
ServiceApplication::where('last_online_at', '<', now()->subSeconds($seconds))->update(['status' => 'exited']);
ServiceDatabase::where('last_online_at', '<', now()->subSeconds($seconds))->update(['status' => 'exited']);
StandalonePostgresql::where('last_online_at', '<', now()->subSeconds($seconds))->update(['status' => 'exited']);
StandaloneRedis::where('last_online_at', '<', now()->subSeconds($seconds))->update(['status' => 'exited']);
StandaloneMongodb::where('last_online_at', '<', now()->subSeconds($seconds))->update(['status' => 'exited']);
StandaloneMysql::where('last_online_at', '<', now()->subSeconds($seconds))->update(['status' => 'exited']);
StandaloneMariadb::where('last_online_at', '<', now()->subSeconds($seconds))->update(['status' => 'exited']);
StandaloneKeydb::where('last_online_at', '<', now()->subSeconds($seconds))->update(['status' => 'exited']);
StandaloneDragonfly::where('last_online_at', '<', now()->subSeconds($seconds))->update(['status' => 'exited']);
StandaloneClickhouse::where('last_online_at', '<', now()->subSeconds($seconds))->update(['status' => 'exited']);
} catch (\Throwable $e) {
return handleError($e);
}
return null;
}
}

View File

@@ -16,7 +16,6 @@ use App\Models\ServiceDatabase;
use App\Notifications\Container\ContainerRestarted;
use Illuminate\Support\Arr;
use Lorisleiva\Actions\Concerns\AsAction;
use Throwable;
class ServerCheck
{
@@ -62,11 +61,11 @@ class ServerCheck
}
if (isset($containerReplicates)) {
foreach ($containerReplicates as $containerReplicate) {
$name = data_get($containerReplicate, 'Name');
$this->containers = $this->containers->map(function ($container) use ($name, $containerReplicate) {
foreach ($containerReplicates as $containerReplica) {
$name = data_get($containerReplica, 'Name');
$this->containers = $this->containers->map(function ($container) use ($name, $containerReplica) {
if (data_get($container, 'Spec.Name') === $name) {
$replicas = data_get($containerReplicate, 'Replicas');
$replicas = data_get($containerReplica, 'Replicas');
$running = str($replicas)->explode('/')[0];
$total = str($replicas)->explode('/')[1];
if ($running === $total) {
@@ -96,9 +95,9 @@ class ServerCheck
$foundProxyContainer = $this->containers->filter(function ($value, $key) {
if ($this->server->isSwarm()) {
return data_get($value, 'Spec.Name') === 'coolify-proxy_traefik';
} else {
return data_get($value, 'Name') === '/coolify-proxy';
}
return data_get($value, 'Name') === '/coolify-proxy';
})->first();
if (! $foundProxyContainer) {
try {
@@ -107,7 +106,7 @@ class ServerCheck
StartProxy::run($this->server, false);
$this->server->team?->notify(new ContainerRestarted('coolify-proxy', $this->server));
}
} catch (Throwable $e) {
} catch (\Throwable $e) {
}
} else {
$this->server->proxy->status = data_get($foundProxyContainer, 'State.Status');
@@ -117,11 +116,9 @@ class ServerCheck
}
}
}
} catch (Throwable $e) {
} catch (\Throwable $e) {
return handleError($e);
}
return null;
}
private function checkLogDrainContainer()
@@ -144,10 +141,12 @@ class ServerCheck
foreach ($this->containers as $container) {
if ($this->isSentinel) {
$labels = Arr::undot(data_get($container, 'labels'));
} elseif ($this->server->isSwarm()) {
$labels = Arr::undot(data_get($container, 'Spec.Labels'));
} else {
$labels = Arr::undot(data_get($container, 'Config.Labels'));
if ($this->server->isSwarm()) {
$labels = Arr::undot(data_get($container, 'Spec.Labels'));
} else {
$labels = Arr::undot(data_get($container, 'Config.Labels'));
}
}
$managed = data_get($labels, 'coolify.managed');
if (! $managed) {
@@ -178,12 +177,12 @@ class ServerCheck
if (str($applicationId)->contains('-')) {
$applicationId = str($applicationId)->before('-');
}
$preview = ApplicationPreview::query()->where('application_id', $applicationId)->where('pull_request_id', $pullRequestId)->first();
$preview = ApplicationPreview::where('application_id', $applicationId)->where('pull_request_id', $pullRequestId)->first();
if ($preview) {
$preview->update(['status' => $containerStatus]);
}
} else {
$application = Application::query()->where('id', $applicationId)->first();
$application = Application::where('id', $applicationId)->first();
if ($application) {
$application->update([
'status' => $containerStatus,
@@ -195,14 +194,14 @@ class ServerCheck
// Service
$subType = data_get($labels, 'coolify.service.subType');
$subId = data_get($labels, 'coolify.service.subId');
$service = Service::query()->where('id', $serviceId)->first();
$service = Service::where('id', $serviceId)->first();
if (! $service) {
continue;
}
if ($subType === 'application') {
$service = ServiceApplication::query()->where('id', $subId)->first();
$service = ServiceApplication::where('id', $subId)->first();
} else {
$service = ServiceDatabase::query()->where('id', $subId)->first();
$service = ServiceDatabase::where('id', $subId)->first();
}
if ($service) {
$service->update([
@@ -215,12 +214,14 @@ class ServerCheck
$foundTcpProxy = $this->containers->filter(function ($value, $key) use ($uuid) {
if ($this->isSentinel) {
return data_get($value, 'name') === $uuid.'-proxy';
}
if ($this->server->isSwarm()) {
return data_get($value, 'Spec.Name') === "coolify-proxy_$uuid";
}
} else {
return data_get($value, 'Name') === "/$uuid-proxy";
if ($this->server->isSwarm()) {
return data_get($value, 'Spec.Name') === "coolify-proxy_$uuid";
} else {
return data_get($value, 'Name') === "/$uuid-proxy";
}
}
})->first();
if (! $foundTcpProxy) {
StartDatabaseProxy::run($service);
@@ -245,12 +246,14 @@ class ServerCheck
$foundTcpProxy = $this->containers->filter(function ($value, $key) use ($uuid) {
if ($this->isSentinel) {
return data_get($value, 'name') === $uuid.'-proxy';
}
if ($this->server->isSwarm()) {
return data_get($value, 'Spec.Name') === "coolify-proxy_$uuid";
}
} else {
if ($this->server->isSwarm()) {
return data_get($value, 'Spec.Name') === "coolify-proxy_$uuid";
} else {
return data_get($value, 'Name') === "/$uuid-proxy";
return data_get($value, 'Name') === "/$uuid-proxy";
}
}
})->first();
if (! $foundTcpProxy) {
StartDatabaseProxy::run($database);

View File

@@ -3,9 +3,7 @@
namespace App\Actions\Server;
use App\Models\Server;
use Exception;
use Lorisleiva\Actions\Concerns\AsAction;
use Throwable;
class StartLogDrain
{
@@ -33,10 +31,9 @@ class StartLogDrain
try {
if ($type === 'none') {
return 'No log drain is enabled.';
}
if ($type === 'newrelic') {
} elseif ($type === 'newrelic') {
if (! $server->settings->is_logdrain_newrelic_enabled) {
throw new Exception('New Relic log drain is not enabled.');
throw new \Exception('New Relic log drain is not enabled.');
}
$config = base64_encode("
[SERVICE]
@@ -71,7 +68,7 @@ class StartLogDrain
");
} elseif ($type === 'highlight') {
if (! $server->settings->is_logdrain_highlight_enabled) {
throw new Exception('Highlight log drain is not enabled.');
throw new \Exception('Highlight log drain is not enabled.');
}
$config = base64_encode('
[SERVICE]
@@ -92,7 +89,7 @@ class StartLogDrain
');
} elseif ($type === 'axiom') {
if (! $server->settings->is_logdrain_axiom_enabled) {
throw new Exception('Axiom log drain is not enabled.');
throw new \Exception('Axiom log drain is not enabled.');
}
$config = base64_encode("
[SERVICE]
@@ -132,12 +129,12 @@ class StartLogDrain
");
} elseif ($type === 'custom') {
if (! $server->settings->is_logdrain_custom_enabled) {
throw new Exception('Custom log drain is not enabled.');
throw new \Exception('Custom log drain is not enabled.');
}
$config = base64_encode($server->settings->logdrain_custom_config);
$parsers = base64_encode($server->settings->logdrain_custom_config_parser);
} else {
throw new Exception('Unknown log drain type.');
throw new \Exception('Unknown log drain type.');
}
if ($type !== 'custom') {
$parsers = base64_encode("
@@ -210,7 +207,7 @@ Files:
"touch $config_path/.env",
];
} else {
throw new Exception('Unknown log drain type.');
throw new \Exception('Unknown log drain type.');
}
$restart_command = [
"echo 'Starting Fluent Bit'",
@@ -219,7 +216,7 @@ Files:
$command = array_merge($command, $add_envs_command, $restart_command);
return instant_remote_process($command, $server);
} catch (Throwable $e) {
} catch (\Throwable $e) {
return handleError($e);
}
}

View File

@@ -3,7 +3,6 @@
namespace App\Actions\Server;
use App\Models\Server;
use Exception;
use Lorisleiva\Actions\Concerns\AsAction;
class StartSentinel
@@ -28,7 +27,7 @@ class StartSentinel
$mountDir = '/data/coolify/sentinel';
$image = "ghcr.io/coollabsio/sentinel:$version";
if (! $endpoint) {
throw new Exception('You should set FQDN in Instance Settings.');
throw new \Exception('You should set FQDN in Instance Settings.');
}
$environments = [
'TOKEN' => $token,

View File

@@ -4,7 +4,6 @@ namespace App\Actions\Server;
use App\Models\Server;
use Lorisleiva\Actions\Concerns\AsAction;
use Throwable;
class StopLogDrain
{
@@ -14,7 +13,7 @@ class StopLogDrain
{
try {
return instant_remote_process(['docker rm -f coolify-log-drain'], $server, false);
} catch (Throwable $e) {
} catch (\Throwable $e) {
return handleError($e);
}
}

View File

@@ -25,7 +25,7 @@ class UpdateCoolify
return;
}
$settings = instanceSettings();
$this->server = Server::query()->find(0);
$this->server = Server::find(0);
if (! $this->server) {
return;
}

View File

@@ -3,7 +3,6 @@
namespace App\Actions\Server;
use App\Models\Server;
use Exception;
use Lorisleiva\Actions\Concerns\AsAction;
class ValidateServer
@@ -35,7 +34,7 @@ class ValidateServer
$server->update([
'validation_logs' => $this->error,
]);
throw new Exception($this->error);
throw new \Exception($this->error);
}
$this->supported_os_type = $server->validateOS();
if (! $this->supported_os_type) {
@@ -43,7 +42,7 @@ class ValidateServer
$server->update([
'validation_logs' => $this->error,
]);
throw new Exception($this->error);
throw new \Exception($this->error);
}
$this->docker_installed = $server->validateDockerEngine();
@@ -53,17 +52,18 @@ class ValidateServer
$server->update([
'validation_logs' => $this->error,
]);
throw new Exception($this->error);
throw new \Exception($this->error);
}
$this->docker_version = $server->validateDockerEngineVersion();
if ($this->docker_version) {
return 'OK';
} else {
$this->error = 'Docker Engine is not installed. Please install Docker manually before continuing: <a target="_blank" class="text-black underline dark:text-white" href="https://docs.docker.com/engine/install/#server">documentation</a>.';
$server->update([
'validation_logs' => $this->error,
]);
throw new \Exception($this->error);
}
$this->error = 'Docker Engine is not installed. Please install Docker manually before continuing: <a target="_blank" class="text-black underline dark:text-white" href="https://docs.docker.com/engine/install/#server">documentation</a>.';
$server->update([
'validation_logs' => $this->error,
]);
throw new Exception($this->error);
}
}

View File

@@ -4,7 +4,6 @@ namespace App\Actions\Service;
use App\Actions\Server\CleanupDocker;
use App\Models\Service;
use Exception;
use Illuminate\Support\Facades\Log;
use Lorisleiva\Actions\Concerns\AsAction;
@@ -33,15 +32,17 @@ class DeleteService
$storagesToDelete->push($storage);
}
}
foreach ($storagesToDelete as $storageToDelete) {
$commands[] = "docker volume rm -f $storageToDelete->name";
foreach ($storagesToDelete as $storage) {
$commands[] = "docker volume rm -f $storage->name";
}
// Execute volume deletion first, this must be done first otherwise volumes will not be deleted.
foreach ($commands as $command) {
$result = instant_remote_process([$command], $server, false);
if ($result !== null && $result !== 0) {
Log::error('Error deleting volumes: '.$result);
if (! empty($commands)) {
foreach ($commands as $command) {
$result = instant_remote_process([$command], $server, false);
if ($result !== null && $result !== 0) {
Log::error('Error deleting volumes: '.$result);
}
}
}
}
@@ -51,8 +52,8 @@ class DeleteService
}
instant_remote_process(["docker rm -f $service->uuid"], $server, throwError: false);
} catch (Exception $e) {
throw new Exception($e->getMessage(), $e->getCode(), $e);
} catch (\Exception $e) {
throw new \Exception($e->getMessage());
} finally {
if ($deleteConfigurations) {
$service->delete_configurations();

View File

@@ -4,7 +4,6 @@ namespace App\Actions\Service;
use App\Actions\Server\CleanupDocker;
use App\Models\Service;
use Exception;
use Lorisleiva\Actions\Concerns\AsAction;
class StopService
@@ -30,10 +29,8 @@ class StopService
CleanupDocker::dispatch($server, true);
}
}
} catch (Exception $e) {
} catch (\Exception $e) {
return $e->getMessage();
}
return null;
}
}

View File

@@ -20,10 +20,11 @@ class ComplexStatusCheck
$application->update(['status' => 'exited:unhealthy']);
continue;
}
$application->additional_servers()->updateExistingPivot($server->id, ['status' => 'exited:unhealthy']);
} else {
$application->additional_servers()->updateExistingPivot($server->id, ['status' => 'exited:unhealthy']);
continue;
continue;
}
}
$container = instant_remote_process(["docker container inspect $(docker container ls -q --filter 'label=coolify.applicationId={$application->id}' --filter 'label=coolify.pullRequestId=0') --format '{{json .}}'"], $server, false);
$container = format_docker_command_output_to_json($container);
@@ -43,14 +44,16 @@ class ComplexStatusCheck
$additional_server->updateExistingPivot($server->id, ['status' => "$containerStatus:$containerHealth"]);
}
}
} elseif ($is_main_server) {
$application->update(['status' => 'exited:unhealthy']);
continue;
} else {
$application->additional_servers()->updateExistingPivot($server->id, ['status' => 'exited:unhealthy']);
if ($is_main_server) {
$application->update(['status' => 'exited:unhealthy']);
continue;
continue;
} else {
$application->additional_servers()->updateExistingPivot($server->id, ['status' => 'exited:unhealthy']);
continue;
}
}
}
}

View File

@@ -9,20 +9,20 @@ class PullImage
{
use AsAction;
public function handle(Service $service)
public function handle(Service $resource)
{
$service->saveComposeConfigs();
$resource->saveComposeConfigs();
$commands[] = 'cd '.$service->workdir();
$commands[] = "echo 'Saved configuration files to {$service->workdir()}.'";
$commands[] = 'cd '.$resource->workdir();
$commands[] = "echo 'Saved configuration files to {$resource->workdir()}.'";
$commands[] = 'docker compose pull';
$server = data_get($service, 'server');
$server = data_get($resource, 'server');
if (! $server) {
return;
}
instant_remote_process($commands, $service->server);
instant_remote_process($commands, $resource->server);
}
}