fix: better server validation and installation process
fix: add destination to queue deployment feat: force start deployment
This commit is contained in:
@@ -15,7 +15,7 @@ class ActivityMonitor extends Component
|
||||
public $isPollingActive = false;
|
||||
|
||||
protected $activity;
|
||||
protected $listeners = ['newMonitorActivity'];
|
||||
protected $listeners = ['activityMonitor' => 'newMonitorActivity'];
|
||||
|
||||
public function newMonitorActivity($activityId, $eventToDispatch = 'activityFinished')
|
||||
{
|
||||
|
@@ -12,6 +12,7 @@ use Livewire\Component;
|
||||
|
||||
class Index extends Component
|
||||
{
|
||||
protected $listeners = ['serverInstalled' => 'validateServer'];
|
||||
public string $currentState = 'welcome';
|
||||
|
||||
public ?string $selectedServerType = null;
|
||||
@@ -93,7 +94,11 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA==
|
||||
$this->serverPublicKey = $this->createdServer->privateKey->publicKey();
|
||||
return $this->validateServer('localhost');
|
||||
} elseif ($this->selectedServerType === 'remote') {
|
||||
$this->privateKeys = PrivateKey::ownedByCurrentTeam(['name'])->where('id', '!=', 0)->get();
|
||||
if (isDev()) {
|
||||
$this->privateKeys = PrivateKey::ownedByCurrentTeam(['name'])->get();
|
||||
} else {
|
||||
$this->privateKeys = PrivateKey::ownedByCurrentTeam(['name'])->where('id', '!=', 0)->get();
|
||||
}
|
||||
if ($this->privateKeys->count() > 0) {
|
||||
$this->selectedExistingPrivateKey = $this->privateKeys->first()->id;
|
||||
}
|
||||
@@ -190,6 +195,10 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA==
|
||||
$this->createdServer->addInitialNetwork();
|
||||
$this->validateServer();
|
||||
}
|
||||
public function installServer()
|
||||
{
|
||||
$this->dispatch('validateServer', true);
|
||||
}
|
||||
public function validateServer()
|
||||
{
|
||||
try {
|
||||
@@ -228,7 +237,7 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA==
|
||||
$this->dockerInstallationStarted = true;
|
||||
$activity = InstallDocker::run($this->createdServer);
|
||||
$this->dispatch('installDocker');
|
||||
$this->dispatch('newMonitorActivity', $activity->id);
|
||||
$this->dispatch('activityMonitor', $activity->id);
|
||||
} catch (\Throwable $e) {
|
||||
$this->dockerInstallationStarted = false;
|
||||
return handleError(error: $e, livewire: $this);
|
||||
|
63
app/Livewire/NewActivityMonitor.php
Normal file
63
app/Livewire/NewActivityMonitor.php
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire;
|
||||
|
||||
use App\Models\User;
|
||||
use Livewire\Component;
|
||||
use Spatie\Activitylog\Models\Activity;
|
||||
|
||||
class NewActivityMonitor extends Component
|
||||
{
|
||||
public ?string $header = null;
|
||||
public $activityId;
|
||||
public $eventToDispatch = 'activityFinished';
|
||||
public $isPollingActive = false;
|
||||
|
||||
protected $activity;
|
||||
protected $listeners = ['newActivityMonitor' => 'newMonitorActivity'];
|
||||
|
||||
public function newMonitorActivity($activityId, $eventToDispatch = 'activityFinished')
|
||||
{
|
||||
$this->activityId = $activityId;
|
||||
$this->eventToDispatch = $eventToDispatch;
|
||||
|
||||
$this->hydrateActivity();
|
||||
|
||||
$this->isPollingActive = true;
|
||||
}
|
||||
|
||||
public function hydrateActivity()
|
||||
{
|
||||
$this->activity = Activity::find($this->activityId);
|
||||
}
|
||||
|
||||
public function polling()
|
||||
{
|
||||
$this->hydrateActivity();
|
||||
// $this->setStatus(ProcessStatus::IN_PROGRESS);
|
||||
$exit_code = data_get($this->activity, 'properties.exitCode');
|
||||
if ($exit_code !== null) {
|
||||
// if ($exit_code === 0) {
|
||||
// // $this->setStatus(ProcessStatus::FINISHED);
|
||||
// } else {
|
||||
// // $this->setStatus(ProcessStatus::ERROR);
|
||||
// }
|
||||
$this->isPollingActive = false;
|
||||
if ($this->eventToDispatch !== null) {
|
||||
if (str($this->eventToDispatch)->startsWith('App\\Events\\')) {
|
||||
$causer_id = data_get($this->activity, 'causer_id');
|
||||
$user = User::find($causer_id);
|
||||
if ($user) {
|
||||
foreach ($user->teams as $team) {
|
||||
$teamId = $team->id;
|
||||
$this->eventToDispatch::dispatch($teamId);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
$this->dispatch($this->eventToDispatch);
|
||||
ray('Dispatched event: ' . $this->eventToDispatch);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -7,8 +7,6 @@ use App\Models\Application;
|
||||
use App\Models\ApplicationDeploymentQueue;
|
||||
use App\Models\Server;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\Process;
|
||||
use Illuminate\Support\Str;
|
||||
use Livewire\Component;
|
||||
|
||||
class DeploymentNavbar extends Component
|
||||
@@ -37,7 +35,15 @@ class DeploymentNavbar extends Component
|
||||
$this->is_debug_enabled = $this->application->settings->is_debug_enabled;
|
||||
$this->dispatch('refreshQueue');
|
||||
}
|
||||
|
||||
public function force_start()
|
||||
{
|
||||
try {
|
||||
force_start_deployment($this->application_deployment_queue);
|
||||
} catch (\Throwable $e) {
|
||||
ray($e);
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
public function cancel()
|
||||
{
|
||||
try {
|
||||
@@ -67,7 +73,6 @@ class DeploymentNavbar extends Component
|
||||
'current_process_id' => null,
|
||||
'status' => ApplicationDeploymentStatus::CANCELLED_BY_USER->value,
|
||||
]);
|
||||
// queue_next_deployment($this->application);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -46,26 +46,6 @@ class Heading extends Component
|
||||
$this->deploy(force_rebuild: true);
|
||||
}
|
||||
|
||||
public function deployNew()
|
||||
{
|
||||
if ($this->application->build_pack === 'dockercompose' && is_null($this->application->docker_compose_raw)) {
|
||||
$this->dispatch('error', 'Please load a Compose file first.');
|
||||
return;
|
||||
}
|
||||
$this->setDeploymentUuid();
|
||||
queue_application_deployment(
|
||||
application: $this->application,
|
||||
deployment_uuid: $this->deploymentUuid,
|
||||
force_rebuild: false,
|
||||
is_new_deployment: true,
|
||||
);
|
||||
return redirect()->route('project.application.deployment.show', [
|
||||
'project_uuid' => $this->parameters['project_uuid'],
|
||||
'application_uuid' => $this->parameters['application_uuid'],
|
||||
'deployment_uuid' => $this->deploymentUuid,
|
||||
'environment_name' => $this->parameters['environment_name'],
|
||||
]);
|
||||
}
|
||||
public function deploy(bool $force_rebuild = false)
|
||||
{
|
||||
if ($this->application->build_pack === 'dockercompose' && is_null($this->application->docker_compose_raw)) {
|
||||
|
@@ -58,19 +58,19 @@ class Heading extends Component
|
||||
{
|
||||
if ($this->database->type() === 'standalone-postgresql') {
|
||||
$activity = StartPostgresql::run($this->database);
|
||||
$this->dispatch('newMonitorActivity', $activity->id);
|
||||
$this->dispatch('activityMonitor', $activity->id);
|
||||
} else if ($this->database->type() === 'standalone-redis') {
|
||||
$activity = StartRedis::run($this->database);
|
||||
$this->dispatch('newMonitorActivity', $activity->id);
|
||||
$this->dispatch('activityMonitor', $activity->id);
|
||||
} else if ($this->database->type() === 'standalone-mongodb') {
|
||||
$activity = StartMongodb::run($this->database);
|
||||
$this->dispatch('newMonitorActivity', $activity->id);
|
||||
$this->dispatch('activityMonitor', $activity->id);
|
||||
} else if ($this->database->type() === 'standalone-mysql') {
|
||||
$activity = StartMysql::run($this->database);
|
||||
$this->dispatch('newMonitorActivity', $activity->id);
|
||||
$this->dispatch('activityMonitor', $activity->id);
|
||||
} else if ($this->database->type() === 'standalone-mariadb') {
|
||||
$activity = StartMariadb::run($this->database);
|
||||
$this->dispatch('newMonitorActivity', $activity->id);
|
||||
$this->dispatch('activityMonitor', $activity->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -129,7 +129,7 @@ class Import extends Component
|
||||
|
||||
if (!empty($this->importCommands)) {
|
||||
$activity = remote_process($this->importCommands, $this->server, ignore_errors: true);
|
||||
$this->dispatch('newMonitorActivity', $activity->id);
|
||||
$this->dispatch('activityMonitor', $activity->id);
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
$this->validated = false;
|
||||
|
@@ -57,7 +57,7 @@ class Navbar extends Component
|
||||
}
|
||||
$this->service->parse();
|
||||
$activity = StartService::run($this->service);
|
||||
$this->dispatch('newMonitorActivity', $activity->id);
|
||||
$this->dispatch('activityMonitor', $activity->id);
|
||||
}
|
||||
public function stop(bool $forceCleanup = false)
|
||||
{
|
||||
@@ -82,6 +82,6 @@ class Navbar extends Component
|
||||
StopService::run($this->service);
|
||||
$this->service->parse();
|
||||
$activity = StartService::run($this->service);
|
||||
$this->dispatch('newMonitorActivity', $activity->id);
|
||||
$this->dispatch('activityMonitor', $activity->id);
|
||||
}
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@ namespace App\Livewire\Project\Service;
|
||||
use App\Models\ServiceApplication;
|
||||
use Livewire\Component;
|
||||
|
||||
class Application extends Component
|
||||
class ServiceApplicationView extends Component
|
||||
{
|
||||
public ServiceApplication $application;
|
||||
public $parameters;
|
||||
@@ -20,7 +20,7 @@ class Application extends Component
|
||||
];
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.project.service.application');
|
||||
return view('livewire.project.service.service-application-view');
|
||||
}
|
||||
public function instantSave()
|
||||
{
|
@@ -115,7 +115,7 @@ class ExecuteContainerCommand extends Component
|
||||
$exec = "docker exec {$this->container} {$cmd}";
|
||||
}
|
||||
$activity = remote_process([$exec], $this->server, ignore_errors: true);
|
||||
$this->dispatch('newMonitorActivity', $activity->id);
|
||||
$this->dispatch('activityMonitor', $activity->id);
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
|
@@ -31,7 +31,7 @@ class RunCommand extends Component
|
||||
$this->validate();
|
||||
try {
|
||||
$activity = remote_process([$this->command], Server::where('uuid', $this->server)->first(), ignore_errors: true);
|
||||
$this->dispatch('newMonitorActivity', $activity->id);
|
||||
$this->dispatch('activityMonitor', $activity->id);
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
|
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Livewire\Server;
|
||||
|
||||
use App\Actions\Server\InstallDocker;
|
||||
use App\Models\Server;
|
||||
use Livewire\Component;
|
||||
|
||||
@@ -14,7 +13,8 @@ class Form extends Component
|
||||
public ?string $wildcard_domain = null;
|
||||
public int $cleanup_after_percentage;
|
||||
public bool $dockerInstallationStarted = false;
|
||||
protected $listeners = ['serverRefresh'];
|
||||
|
||||
protected $listeners = ['serverInstalled'];
|
||||
|
||||
protected $rules = [
|
||||
'server.name' => 'required',
|
||||
@@ -49,9 +49,10 @@ class Form extends Component
|
||||
$this->wildcard_domain = $this->server->settings->wildcard_domain;
|
||||
$this->cleanup_after_percentage = $this->server->settings->cleanup_after_percentage;
|
||||
}
|
||||
public function serverRefresh($install = true)
|
||||
public function serverInstalled()
|
||||
{
|
||||
$this->validateServer($install);
|
||||
$this->server->refresh();
|
||||
$this->server->settings->refresh();
|
||||
}
|
||||
public function instantSave()
|
||||
{
|
||||
@@ -64,13 +65,6 @@ class Form extends Component
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
public function installDocker()
|
||||
{
|
||||
$this->dispatch('installDocker');
|
||||
$this->dockerInstallationStarted = true;
|
||||
$activity = InstallDocker::run($this->server);
|
||||
$this->dispatch('newMonitorActivity', $activity->id);
|
||||
}
|
||||
public function checkLocalhostConnection()
|
||||
{
|
||||
$uptime = $this->server->validateConnection();
|
||||
@@ -80,48 +74,13 @@ class Form extends Component
|
||||
$this->server->settings->is_usable = true;
|
||||
$this->server->settings->save();
|
||||
} else {
|
||||
$this->dispatch('error', 'Server is not reachable.<br>Please validate your configuration and connection.<br><br>Check this <a target="_blank" class="underline" href="https://coolify.io/docs/server/openssh">documentation</a> for further help.');
|
||||
$this->dispatch('error', 'Server is not reachable.', 'Please validate your configuration and connection.<br><br>Check this <a target="_blank" class="underline" href="https://coolify.io/docs/server/openssh">documentation</a> for further help.');
|
||||
return;
|
||||
}
|
||||
}
|
||||
public function validateServer($install = true)
|
||||
{
|
||||
try {
|
||||
$uptime = $this->server->validateConnection();
|
||||
if (!$uptime) {
|
||||
$install && $this->dispatch('error', 'Server is not reachable.<br>Please validate your configuration and connection.<br><br>Check this <a target="_blank" class="underline" href="https://coolify.io/docs/server/openssh">documentation</a> for further help.');
|
||||
return;
|
||||
}
|
||||
$supported_os_type = $this->server->validateOS();
|
||||
if (!$supported_os_type) {
|
||||
$install && $this->dispatch('error', 'Server OS type is not supported for automated installation. Please install Docker manually before continuing: <a target="_blank" class="underline" href="https://docs.docker.com/engine/install/#server">documentation</a>.');
|
||||
return;
|
||||
}
|
||||
$dockerInstalled = $this->server->validateDockerEngine();
|
||||
if ($dockerInstalled) {
|
||||
$install && $this->dispatch('success', 'Docker Engine is installed.<br> Checking version.');
|
||||
} else {
|
||||
$install && $this->installDocker();
|
||||
return;
|
||||
}
|
||||
$dockerVersion = $this->server->validateDockerEngineVersion();
|
||||
if ($dockerVersion) {
|
||||
$install && $this->dispatch('success', 'Docker Engine version is 22+.');
|
||||
} else {
|
||||
$install && $this->installDocker();
|
||||
return;
|
||||
}
|
||||
if ($this->server->isSwarm()) {
|
||||
$swarmInstalled = $this->server->validateDockerSwarm();
|
||||
if ($swarmInstalled) {
|
||||
$install && $this->dispatch('success', 'Docker Swarm is initiated.');
|
||||
}
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
} finally {
|
||||
$this->dispatch('proxyStatusUpdated');
|
||||
}
|
||||
$this->dispatch('validateServer', $install);
|
||||
}
|
||||
|
||||
public function submit()
|
||||
|
@@ -71,7 +71,7 @@ class Deploy extends Component
|
||||
{
|
||||
try {
|
||||
$activity = StartProxy::run($this->server);
|
||||
$this->dispatch('newMonitorActivity', $activity->id, ProxyStatusChanged::class);
|
||||
$this->dispatch('activityMonitor', $activity->id, ProxyStatusChanged::class);
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
|
@@ -12,10 +12,8 @@ class Status extends Component
|
||||
public Server $server;
|
||||
public bool $polling = false;
|
||||
public int $numberOfPolls = 0;
|
||||
|
||||
protected $listeners = ['proxyStatusUpdated', 'startProxyPolling'];
|
||||
public function mount() {
|
||||
}
|
||||
|
||||
public function startProxyPolling()
|
||||
{
|
||||
$this->checkProxy();
|
||||
|
@@ -11,7 +11,7 @@ class Show extends Component
|
||||
use AuthorizesRequests;
|
||||
public ?Server $server = null;
|
||||
public $parameters = [];
|
||||
protected $listeners = ['proxyStatusUpdated' => '$refresh'];
|
||||
protected $listeners = ['serverInstalled' => '$refresh'];
|
||||
public function mount()
|
||||
{
|
||||
$this->parameters = get_route_parameters();
|
||||
|
100
app/Livewire/Server/ValidateAndInstall.php
Normal file
100
app/Livewire/Server/ValidateAndInstall.php
Normal file
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Server;
|
||||
|
||||
use App\Models\Server;
|
||||
use Livewire\Component;
|
||||
|
||||
class ValidateAndInstall extends Component
|
||||
{
|
||||
public Server $server;
|
||||
public int $number_of_tries = 0;
|
||||
public int $max_tries = 1;
|
||||
public bool $install = true;
|
||||
public $uptime = null;
|
||||
public $supported_os_type = null;
|
||||
public $docker_installed = null;
|
||||
public $docker_version = null;
|
||||
public $error = null;
|
||||
|
||||
protected $listeners = ['validateServer', 'validateDockerEngine'];
|
||||
|
||||
public function validateServer(bool $install = true)
|
||||
{
|
||||
$this->install = $install;
|
||||
$this->uptime = null;
|
||||
$this->supported_os_type = null;
|
||||
$this->docker_installed = null;
|
||||
$this->docker_version = null;
|
||||
|
||||
try {
|
||||
$this->validateConnection();
|
||||
$this->validateOS();
|
||||
$this->validateDockerEngine();
|
||||
|
||||
if ($this->server->isSwarm()) {
|
||||
$swarmInstalled = $this->server->validateDockerSwarm();
|
||||
if ($swarmInstalled) {
|
||||
$this->dispatch('success', 'Docker Swarm is initiated.');
|
||||
}
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
public function validateConnection()
|
||||
{
|
||||
$this->uptime = $this->server->validateConnection();
|
||||
if (!$this->uptime) {
|
||||
$this->dispatch('error', 'Server is not reachable.', 'Please validate your configuration and connection.<br><br>Check this <a target="_blank" class="underline" href="https://coolify.io/docs/server/openssh">documentation</a> for further help.');
|
||||
return;
|
||||
}
|
||||
}
|
||||
public function validateOS()
|
||||
{
|
||||
$this->supported_os_type = $this->server->validateOS();
|
||||
if (!$this->supported_os_type) {
|
||||
$this->dispatch('error', 'Server OS type is not supported.', 'Please install Docker manually before continuing: <a target="_blank" class="underline" href="https://docs.docker.com/engine/install/#server">documentation</a>.');
|
||||
return;
|
||||
}
|
||||
}
|
||||
public function validateDockerEngine()
|
||||
{
|
||||
$this->docker_installed = $this->server->validateDockerEngine();
|
||||
if (!$this->docker_installed) {
|
||||
if ($this->install) {
|
||||
ray($this->number_of_tries, $this->max_tries);
|
||||
if ($this->number_of_tries == $this->max_tries) {
|
||||
$this->error = 'Docker Engine could not be installed. Please install Docker manually before continuing: <a target="_blank" class="underline" href="https://docs.docker.com/engine/install/#server">documentation</a>.';
|
||||
return;
|
||||
} else {
|
||||
$activity = $this->server->installDocker();
|
||||
$this->number_of_tries++;
|
||||
$this->dispatch('newActivityMonitor', $activity->id, 'validateDockerEngine');
|
||||
return;
|
||||
|
||||
}
|
||||
} else {
|
||||
$this->dispatch('error', 'Docker Engine is not installed.', 'Please install Docker manually before continuing: <a target="_blank" class="underline" href="https://docs.docker.com/engine/install/#server">documentation</a>.');
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
$this->validateDockerVersion();
|
||||
}
|
||||
}
|
||||
public function validateDockerVersion()
|
||||
{
|
||||
$this->docker_version = $this->server->validateDockerEngineVersion();
|
||||
if ($this->docker_version) {
|
||||
$this->dispatch('serverInstalled');
|
||||
$this->dispatch('success', 'Server validated successfully.');
|
||||
} else {
|
||||
$this->dispatch('error', 'Docker Engine version is not 22+.', 'Please install Docker manually before continuing: <a target="_blank" class="underline" href="https://docs.docker.com/engine/install/#server">documentation</a>.');
|
||||
return;
|
||||
}
|
||||
}
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.server.validate-and-install');
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user