mirror of
https://github.com/tiennm99/coolify.git
synced 2026-10-17 06:14:40 +00:00
feat: implement prerequisite validation and installation for server setup
This commit is contained in:
1 parent
ce4f8d02a2
commit
01957f2752
9 files changed
+218
-32
No files matched your search
@@ -59,8 +59,6 @@ class InstallDocker
|
||||
$command = collect([]);
|
||||
if (isDev() && $server->id === 0) {
|
||||
$command = $command->merge([
|
||||
"echo 'Installing Prerequisites...'",
|
||||
'sleep 1',
|
||||
"echo 'Installing Docker Engine...'",
|
||||
"echo 'Configuring Docker Engine (merging existing configuration with the required)...'",
|
||||
'sleep 4',
|
||||
@@ -70,35 +68,6 @@ class InstallDocker
|
||||
|
||||
return remote_process($command, $server);
|
||||
} else {
|
||||
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...'",
|
||||
]);
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Server;
|
||||
|
||||
use App\Models\Server;
|
||||
use Lorisleiva\Actions\Concerns\AsAction;
|
||||
|
||||
class InstallPrerequisites
|
||||
{
|
||||
use AsAction;
|
||||
|
||||
public string $jobQueue = 'high';
|
||||
|
||||
public function handle(Server $server)
|
||||
{
|
||||
$supported_os_type = $server->validateOS();
|
||||
if (! $supported_os_type) {
|
||||
throw new \Exception('Server OS type is not supported for automated installation. Please install prerequisites manually.');
|
||||
}
|
||||
|
||||
$command = collect([]);
|
||||
|
||||
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 type for prerequisites installation');
|
||||
}
|
||||
|
||||
$command->push("echo 'Prerequisites installed successfully.'");
|
||||
|
||||
return remote_process($command, $server);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Server;
|
||||
|
||||
use App\Models\Server;
|
||||
use Lorisleiva\Actions\Concerns\AsAction;
|
||||
|
||||
class ValidatePrerequisites
|
||||
{
|
||||
use AsAction;
|
||||
|
||||
public string $jobQueue = 'high';
|
||||
|
||||
public function handle(Server $server): bool
|
||||
{
|
||||
$requiredCommands = ['git', 'curl', 'jq'];
|
||||
|
||||
foreach ($requiredCommands as $cmd) {
|
||||
$found = instant_remote_process(["command -v {$cmd}"], $server, false);
|
||||
if (! $found) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -45,6 +45,15 @@ class ValidateServer
|
||||
throw new \Exception($this->error);
|
||||
}
|
||||
|
||||
$prerequisitesInstalled = $server->validatePrerequisites();
|
||||
if (! $prerequisitesInstalled) {
|
||||
$this->error = 'Prerequisites (git, curl, jq) are not installed. Please install them before continuing or use the validation with installation endpoint.';
|
||||
$server->update([
|
||||
'validation_logs' => $this->error,
|
||||
]);
|
||||
throw new \Exception($this->error);
|
||||
}
|
||||
|
||||
$this->docker_installed = $server->validateDockerEngine();
|
||||
$this->docker_compose_installed = $server->validateDockerCompose();
|
||||
if (! $this->docker_installed || ! $this->docker_compose_installed) {
|
||||
|
||||
@@ -72,6 +72,37 @@ class ValidateAndInstallServerJob implements ShouldQueue
|
||||
return;
|
||||
}
|
||||
|
||||
// Check and install prerequisites
|
||||
$prerequisitesInstalled = $this->server->validatePrerequisites();
|
||||
if (! $prerequisitesInstalled) {
|
||||
if ($this->numberOfTries >= $this->maxTries) {
|
||||
$errorMessage = 'Prerequisites (git, curl, jq) could not be installed after '.$this->maxTries.' attempts. Please install them manually before continuing.';
|
||||
$this->server->update([
|
||||
'validation_logs' => $errorMessage,
|
||||
'is_validating' => false,
|
||||
]);
|
||||
Log::error('ValidateAndInstallServer: Prerequisites installation failed after max tries', [
|
||||
'server_id' => $this->server->id,
|
||||
'attempts' => $this->numberOfTries,
|
||||
]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Log::info('ValidateAndInstallServer: Installing prerequisites', [
|
||||
'server_id' => $this->server->id,
|
||||
'attempt' => $this->numberOfTries + 1,
|
||||
]);
|
||||
|
||||
// Install prerequisites
|
||||
$this->server->installPrerequisites();
|
||||
|
||||
// Retry validation after installation
|
||||
self::dispatch($this->server, $this->numberOfTries + 1)->delay(now()->addSeconds(30));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if Docker is installed
|
||||
$dockerInstalled = $this->server->validateDockerEngine();
|
||||
$dockerComposeInstalled = $this->server->validateDockerCompose();
|
||||
|
||||
@@ -320,6 +320,21 @@ class Index extends Component
|
||||
return handleError(error: $e, livewire: $this);
|
||||
}
|
||||
|
||||
try {
|
||||
// Check prerequisites
|
||||
$prerequisitesInstalled = $this->createdServer->validatePrerequisites();
|
||||
if (! $prerequisitesInstalled) {
|
||||
$this->createdServer->installPrerequisites();
|
||||
// Recheck after installation
|
||||
$prerequisitesInstalled = $this->createdServer->validatePrerequisites();
|
||||
if (! $prerequisitesInstalled) {
|
||||
throw new \Exception('Prerequisites (git, curl, jq) could not be installed. Please install them manually.');
|
||||
}
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
return handleError(error: $e, livewire: $this);
|
||||
}
|
||||
|
||||
try {
|
||||
$dockerVersion = instant_remote_process(["docker version|head -2|grep -i version| awk '{print $2}'"], $this->createdServer, true);
|
||||
$dockerVersion = checkMinimumDockerEngineVersion($dockerVersion);
|
||||
|
||||
@@ -25,6 +25,8 @@ class ValidateAndInstall extends Component
|
||||
|
||||
public $supported_os_type = null;
|
||||
|
||||
public $prerequisites_installed = null;
|
||||
|
||||
public $docker_installed = null;
|
||||
|
||||
public $docker_compose_installed = null;
|
||||
@@ -33,12 +35,15 @@ class ValidateAndInstall extends Component
|
||||
|
||||
public $error = null;
|
||||
|
||||
public string $installationStep = 'Prerequisites';
|
||||
|
||||
public bool $ask = false;
|
||||
|
||||
protected $listeners = [
|
||||
'init',
|
||||
'validateConnection',
|
||||
'validateOS',
|
||||
'validatePrerequisites',
|
||||
'validateDockerEngine',
|
||||
'validateDockerVersion',
|
||||
'refresh' => '$refresh',
|
||||
@@ -48,6 +53,7 @@ class ValidateAndInstall extends Component
|
||||
{
|
||||
$this->uptime = null;
|
||||
$this->supported_os_type = null;
|
||||
$this->prerequisites_installed = null;
|
||||
$this->docker_installed = null;
|
||||
$this->docker_version = null;
|
||||
$this->docker_compose_installed = null;
|
||||
@@ -69,6 +75,7 @@ class ValidateAndInstall extends Component
|
||||
$this->authorize('update', $this->server);
|
||||
$this->uptime = null;
|
||||
$this->supported_os_type = null;
|
||||
$this->prerequisites_installed = null;
|
||||
$this->docker_installed = null;
|
||||
$this->docker_compose_installed = null;
|
||||
$this->docker_version = null;
|
||||
@@ -103,6 +110,40 @@ class ValidateAndInstall extends Component
|
||||
|
||||
return;
|
||||
}
|
||||
$this->dispatch('validatePrerequisites');
|
||||
}
|
||||
|
||||
public function validatePrerequisites()
|
||||
{
|
||||
$this->prerequisites_installed = $this->server->validatePrerequisites();
|
||||
if (! $this->prerequisites_installed) {
|
||||
if ($this->install) {
|
||||
if ($this->number_of_tries == $this->max_tries) {
|
||||
$this->error = 'Prerequisites (git, curl, jq) could not be installed. Please install them manually before continuing.';
|
||||
$this->server->update([
|
||||
'validation_logs' => $this->error,
|
||||
]);
|
||||
|
||||
return;
|
||||
} else {
|
||||
if ($this->number_of_tries <= $this->max_tries) {
|
||||
$this->installationStep = 'Prerequisites';
|
||||
$activity = $this->server->installPrerequisites();
|
||||
$this->number_of_tries++;
|
||||
$this->dispatch('activityMonitor', $activity->id, 'init', $this->number_of_tries);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
$this->error = 'Prerequisites (git, curl, jq) are not installed. Please install them before continuing.';
|
||||
$this->server->update([
|
||||
'validation_logs' => $this->error,
|
||||
]);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
$this->dispatch('validateDockerEngine');
|
||||
}
|
||||
|
||||
@@ -121,6 +162,7 @@ class ValidateAndInstall extends Component
|
||||
return;
|
||||
} else {
|
||||
if ($this->number_of_tries <= $this->max_tries) {
|
||||
$this->installationStep = 'Docker';
|
||||
$activity = $this->server->installDocker();
|
||||
$this->number_of_tries++;
|
||||
$this->dispatch('activityMonitor', $activity->id, 'init', $this->number_of_tries);
|
||||
|
||||
@@ -4,7 +4,9 @@ namespace App\Models;
|
||||
|
||||
use App\Actions\Proxy\StartProxy;
|
||||
use App\Actions\Server\InstallDocker;
|
||||
use App\Actions\Server\InstallPrerequisites;
|
||||
use App\Actions\Server\StartSentinel;
|
||||
use App\Actions\Server\ValidatePrerequisites;
|
||||
use App\Enums\ProxyTypes;
|
||||
use App\Events\ServerReachabilityChanged;
|
||||
use App\Helpers\SslHelper;
|
||||
@@ -1184,6 +1186,16 @@ $schema://$host {
|
||||
return InstallDocker::run($this);
|
||||
}
|
||||
|
||||
public function validatePrerequisites(): bool
|
||||
{
|
||||
return ValidatePrerequisites::run($this);
|
||||
}
|
||||
|
||||
public function installPrerequisites()
|
||||
{
|
||||
return InstallPrerequisites::run($this);
|
||||
}
|
||||
|
||||
public function validateDockerEngine($throwError = false)
|
||||
{
|
||||
$dockerBinary = instant_remote_process(['command -v docker'], $this, false, no_sudo: true);
|
||||
|
||||
Reference in new issue
Block a user