This commit is contained in:
Andras Bacsai
2024-10-14 13:32:36 +02:00
parent 1f193d465d
commit b2e515f770
6 changed files with 120 additions and 29 deletions

View File

@@ -38,7 +38,7 @@ class Kernel extends ConsoleKernel
$schedule->job(new CleanupInstanceStuffsJob)->everyMinute()->onOneServer();
// Server Jobs
$this->check_scheduled_backups($schedule);
$this->check_resources($schedule);
// $this->check_resources($schedule);
$this->check_scheduled_tasks($schedule);
$schedule->command('uploads:clear')->everyTwoMinutes();

View File

@@ -2,14 +2,16 @@
namespace App\Jobs;
use App\Actions\Proxy\StartProxy;
use App\Models\Application;
use App\Models\ApplicationPreview;
use App\Models\Server;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
class PushServerUpdateJob implements ShouldQueue
@@ -25,7 +27,15 @@ class PushServerUpdateJob implements ShouldQueue
return isDev() ? 1 : 3;
}
public function __construct(public Server $server, public $data) {}
public function __construct(public Server $server, public $data)
{
// TODO: Handle multiple servers
// TODO: Handle Preview deployments
// TODO: Handle DB TCP proxies
// TODO: Handle DBs
// TODO: Handle services
// TODO: Handle proxies
}
public function handle()
{
@@ -37,17 +47,90 @@ class PushServerUpdateJob implements ShouldQueue
if ($containers->isEmpty()) {
return;
}
$foundApplicationIds = collect();
$foundServiceIds = collect();
$foundProxy = false;
foreach ($containers as $container) {
$containerStatus = data_get($container, 'status', 'exited');
$containerHealth = data_get($container, 'health', 'unhealthy');
$containerStatus = data_get($container, 'state', 'exited');
$containerHealth = data_get($container, 'health_status', 'unhealthy');
$containerStatus = "$containerStatus ($containerHealth)";
$labels = collect(data_get($container, 'labels'));
$coolify_managed = $labels->has('coolify.managed');
if ($coolify_managed) {
if ($labels->has('coolify.applicationId')) {
$applicationId = $labels->get('coolify.applicationId');
$pullRequestId = data_get($labels, 'coolify.pullRequestId', '0');
$foundApplicationIds->push($applicationId);
try {
$this->updateApplicationStatus($applicationId, $pullRequestId, $containerStatus);
} catch (\Exception $e) {
Log::error($e);
}
} elseif ($labels->has('coolify.serviceId')) {
$serviceId = $labels->get('coolify.serviceId');
$foundServiceIds->push($serviceId);
Log::info("Service: $serviceId, $containerStatus");
} else {
$name = data_get($container, 'name');
$uuid = $labels->get('com.docker.compose.service');
$type = $labels->get('coolify.type');
if ($name === 'coolify-proxy') {
$foundProxy = true;
Log::info("Proxy: $uuid, $containerStatus");
} elseif ($type === 'service') {
Log::info("Service: $uuid, $containerStatus");
} else {
Log::info("Database: $uuid, $containerStatus");
}
}
Log::info("$applicationId, $containerStatus");
}
}
// If proxy is not found, start it
if (! $foundProxy && $this->server->isProxyShouldRun()) {
Log::info('Proxy not found, starting it');
StartProxy::dispatch($this->server);
}
// Update not found applications
$allApplicationIds = $this->server->applications()->pluck('id');
$notFoundApplicationIds = $allApplicationIds->diff($foundApplicationIds);
if ($notFoundApplicationIds->isNotEmpty()) {
Log::info('Not found application ids', ['application_ids' => $notFoundApplicationIds]);
$this->updateNotFoundApplications($notFoundApplicationIds);
}
}
private function updateApplicationStatus(string $applicationId, string $pullRequestId, string $containerStatus)
{
if ($pullRequestId === '0') {
$application = Application::find($applicationId);
if (! $application) {
return;
}
$application->status = $containerStatus;
$application->save();
Log::info('Application updated', ['application_id' => $applicationId, 'status' => $containerStatus]);
} else {
$application = ApplicationPreview::where('application_id', $applicationId)->where('pull_request_id', $pullRequestId)->first();
if (! $application) {
return;
}
$application->status = $containerStatus;
$application->save();
}
}
private function updateNotFoundApplications(Collection $applicationIds)
{
$applicationIds->each(function ($applicationId) {
Log::info('Updating application status', ['application_id' => $applicationId, 'status' => 'exited']);
$application = Application::find($applicationId);
if ($application) {
$application->status = 'exited';
$application->save();
Log::info('Application status updated', ['application_id' => $applicationId, 'status' => 'exited']);
}
});
}
}

View File

@@ -17,8 +17,6 @@ use Spatie\SchemalessAttributes\Casts\SchemalessAttributes;
use Spatie\SchemalessAttributes\SchemalessAttributesTrait;
use Spatie\Url\Url;
use Symfony\Component\Yaml\Yaml;
use Illuminate\Support\Str;
#[OA\Schema(
description: 'Server model',
@@ -536,8 +534,10 @@ $schema://$host {
$encrypted = encrypt($token);
$this->settings->sentinel_token = $encrypted;
$this->settings->save();
return $encrypted;
}
public function isSentinelEnabled()
{
return $this->isMetricsEnabled() || $this->isServerApiEnabled();
@@ -989,7 +989,8 @@ $schema://$host {
public function isProxyShouldRun()
{
if ($this->proxyType() === ProxyTypes::NONE->value || $this->settings->is_build_server) {
// TODO: Do we need "|| $this->proxy->force_stop" here?
if ($this->proxyType() === ProxyTypes::NONE->value || $this->isBuildServer()) {
return false;
}

View File

@@ -19,6 +19,9 @@ return new class extends Migration
$table->integer('sentinel_metrics_refresh_rate_seconds')->default(5);
$table->integer('sentinel_metrics_history_days')->default(30);
});
Schema::table('servers', function (Blueprint $table) {
$table->dateTime('sentinel_update_at')->default(now());
});
}
/**
@@ -34,5 +37,8 @@ return new class extends Migration
$table->dropColumn('sentinel_metrics_refresh_rate_seconds');
$table->dropColumn('sentinel_metrics_history_days');
});
Schema::table('servers', function (Blueprint $table) {
$table->dropColumn('sentinel_update_at');
});
}
};

View File

@@ -282,7 +282,7 @@
{{-- @endif --}}
</div>
@if (isDev())
<x-forms.button wire:click="getPushData">Get Push Data</x-forms.button>
<x-forms.button wire:click="getPushData"> Push Test </x-forms.button>
{{-- <div class="w-64">
<x-forms.checkbox instantSave id="server.settings.is_metrics_enabled" label="Enable Metrics" />
<x-forms.button>Start Sentinel</x-forms.button>

View File

@@ -15,7 +15,6 @@ use App\Http\Middleware\IgnoreReadOnlyApiToken;
use App\Http\Middleware\OnlyRootApiToken;
use App\Jobs\PushServerUpdateJob;
use App\Models\Server;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Route;
Route::get('/health', [OtherController::class, 'healthcheck']);
@@ -149,7 +148,9 @@ Route::group([
return response()->json(['message' => 'Server not found'], 404);
}
$data = request()->all();
$server->update(['sentinel_update_at' => now()]);
PushServerUpdateJob::dispatch($server, $data);
return response()->json(['message' => 'ok'], 200);
});
});