@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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']),
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ class UpdateCoolify
|
||||
return;
|
||||
}
|
||||
$settings = instanceSettings();
|
||||
$this->server = Server::query()->find(0);
|
||||
$this->server = Server::find(0);
|
||||
if (! $this->server) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user