diff --git a/app/Http/Controllers/Api/Deploy.php b/app/Http/Controllers/Api/Deploy.php index 21da51d66..27d4b1ea0 100644 --- a/app/Http/Controllers/Api/Deploy.php +++ b/app/Http/Controllers/Api/Deploy.php @@ -14,7 +14,7 @@ use Illuminate\Support\Collection; use Visus\Cuid2\Cuid2; -class Deploy extends Controller +class APIDeploy extends Controller { public function deploy(Request $request) { diff --git a/app/Http/Controllers/Api/Project.php b/app/Http/Controllers/Api/Project.php index fa2ba34bb..110e51803 100644 --- a/app/Http/Controllers/Api/Project.php +++ b/app/Http/Controllers/Api/Project.php @@ -6,7 +6,7 @@ use App\Models\Project as ModelsProject; use Illuminate\Http\Request; -class Project extends Controller +class APIProject extends Controller { public function projects(Request $request) { diff --git a/app/Http/Controllers/Api/Server.php b/app/Http/Controllers/Api/Server.php index e7b071a43..bab37928f 100644 --- a/app/Http/Controllers/Api/Server.php +++ b/app/Http/Controllers/Api/Server.php @@ -6,7 +6,7 @@ use App\Models\Server as ModelsServer; use Illuminate\Http\Request; -class Server extends Controller +class APIServer extends Controller { public function servers(Request $request) { diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php index 61cda4fc6..0949ef5e6 100644 --- a/app/Jobs/ApplicationDeploymentJob.php +++ b/app/Jobs/ApplicationDeploymentJob.php @@ -1675,7 +1675,6 @@ public function failed(Throwable $exception): void ); } } - $this->next(ApplicationDeploymentStatus::FAILED->value); } } diff --git a/app/Jobs/ServerOverflowJob.php b/app/Jobs/ServerLimitCheckJob.php similarity index 62% rename from app/Jobs/ServerOverflowJob.php rename to app/Jobs/ServerLimitCheckJob.php index af7b7a927..052260895 100644 --- a/app/Jobs/ServerOverflowJob.php +++ b/app/Jobs/ServerLimitCheckJob.php @@ -3,7 +3,8 @@ namespace App\Jobs; use App\Models\Team; -use App\Notifications\Server\DisabledDueToOverflow; +use App\Notifications\Server\ForceDisabled; +use App\Notifications\Server\ForceEnabled; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldBeEncrypted; use Illuminate\Contracts\Queue\ShouldQueue; @@ -12,7 +13,7 @@ use Illuminate\Queue\Middleware\WithoutOverlapping; use Illuminate\Queue\SerializesModels; -class ServerOverflowJob implements ShouldQueue, ShouldBeEncrypted +class ServerLimitCheckJob implements ShouldQueue, ShouldBeEncrypted { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; @@ -37,26 +38,31 @@ public function uniqueId(): int public function handle() { try { - ray('ServerOverflowJob'); $servers = $this->team->servers; $servers_count = $servers->count(); $limit = $this->team->limits['serverLimit']; $number_of_servers_to_disable = $servers_count - $limit; - ray($number_of_servers_to_disable, $servers_count, $limit); + ray('ServerLimitCheckJob', $this->team->uuid, $servers_count, $limit, $number_of_servers_to_disable); if ($number_of_servers_to_disable > 0) { ray('Disabling servers'); - $servers = $servers->sortBy('created_at'); + $servers = $servers->sortbyDesc('created_at'); $servers_to_disable = $servers->take($number_of_servers_to_disable); $servers_to_disable->each(function ($server) { - $server->disableServerDueToOverflow(); - $this->team->notify(new DisabledDueToOverflow($server)); + $server->forceDisableServer(); + $this->team->notify(new ForceDisabled($server)); + }); + } else if ($number_of_servers_to_disable === 0) { + $servers->each(function ($server) { + if ($server->isForceDisabled()) { + $server->forceEnableServer(); + $this->team->notify(new ForceEnabled($server)); + } }); } } catch (\Throwable $e) { - send_internal_notification('ServerOverflowJob failed with: ' . $e->getMessage()); + send_internal_notification('ServerLimitCheckJob failed with: ' . $e->getMessage()); ray($e->getMessage()); return handleError($e); } } - } diff --git a/app/Livewire/Admin/Index.php b/app/Livewire/Admin/Index.php index 4ff4ff21b..27e912eed 100644 --- a/app/Livewire/Admin/Index.php +++ b/app/Livewire/Admin/Index.php @@ -3,6 +3,7 @@ namespace App\Livewire\Admin; use App\Models\User; +use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Crypt; use Livewire\Component; @@ -27,6 +28,7 @@ public function switchUser(int $user_id) auth()->login($user); if ($user_id === 0) { + Cache::forget('team:0'); session()->forget('adminToken'); } else { $token_payload = [ @@ -35,6 +37,7 @@ public function switchUser(int $user_id) $token = Crypt::encrypt($token_payload); session(['adminToken' => $token]); } + session()->regenerate(); return refreshSession(); } public function render() diff --git a/app/Livewire/Tags/Show.php b/app/Livewire/Tags/Show.php index 05b25955a..c0c975f6d 100644 --- a/app/Livewire/Tags/Show.php +++ b/app/Livewire/Tags/Show.php @@ -2,7 +2,7 @@ namespace App\Livewire\Tags; -use App\Http\Controllers\Api\Deploy; +use App\Http\Controllers\Api\APIDeploy as Deploy; use App\Models\ApplicationDeploymentQueue; use App\Models\Tag; use Livewire\Component; diff --git a/app/Models/Server.php b/app/Models/Server.php index 4272761a5..fc400935a 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -10,6 +10,7 @@ use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\Storage; use Spatie\SchemalessAttributes\Casts\SchemalessAttributes; use Spatie\SchemalessAttributes\SchemalessAttributesTrait; use Illuminate\Support\Str; @@ -69,7 +70,7 @@ static public function ownedByCurrentTeam(array $select = ['*']) static public function isUsable() { - return Server::ownedByCurrentTeam()->whereRelation('settings', 'is_reachable', true)->whereRelation('settings', 'is_usable', true)->whereRelation('settings', 'is_swarm_worker', false)->whereRelation('settings', 'is_build_server', false); + return Server::ownedByCurrentTeam()->whereRelation('settings', 'is_reachable', true)->whereRelation('settings', 'is_usable', true)->whereRelation('settings', 'is_swarm_worker', false)->whereRelation('settings', 'is_build_server', false)->whereRelation('settings', 'force_disabled', false); } static public function destinationsByServer(string $server_id) @@ -149,13 +150,31 @@ public function skipServer() ray('skipping 1.2.3.4'); return true; } + if ($this->settings->force_disabled === true) { + ray('force_disabled'); + return true; + } return false; } - public function disableServerDueToOverflow() { + public function isForceDisabled() + { + return $this->settings->force_disabled; + } + public function forceEnableServer() + { $this->settings->update([ - 'disabled_by_overflow' => true, + 'force_disabled' => false, ]); } + public function forceDisableServer() + { + $this->settings->update([ + 'force_disabled' => true, + ]); + $sshKeyFileLocation = "id.root@{$this->uuid}"; + Storage::disk('ssh-keys')->delete($sshKeyFileLocation); + Storage::disk('ssh-mux')->delete($this->muxFilename()); + } public function isServerReady(int $tries = 3) { if ($this->skipServer()) { @@ -379,7 +398,7 @@ public function isProxyShouldRun() } public function isFunctional() { - return $this->settings->is_reachable && $this->settings->is_usable; + return $this->settings->is_reachable && $this->settings->is_usable && !$this->settings->force_disabled; } public function isLogDrainEnabled() { diff --git a/app/Notifications/Server/DisabledDueToOverflow.php b/app/Notifications/Server/ForceDisabled.php similarity index 93% rename from app/Notifications/Server/DisabledDueToOverflow.php rename to app/Notifications/Server/ForceDisabled.php index 957d9c866..4bce44e46 100644 --- a/app/Notifications/Server/DisabledDueToOverflow.php +++ b/app/Notifications/Server/ForceDisabled.php @@ -11,7 +11,7 @@ use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Notifications\Notification; -class DisabledDueToOverflow extends Notification implements ShouldQueue +class ForceDisabled extends Notification implements ShouldQueue { use Queueable; @@ -43,7 +43,7 @@ public function toMail(): MailMessage { $mail = new MailMessage(); $mail->subject("Coolify: Server ({$this->server->name}) disabled because it is not paid!"); - $mail->view('emails.server-disabled-due-to-overflow', [ + $mail->view('emails.server-force-disabled', [ 'name' => $this->server->name, ]); return $mail; diff --git a/app/Notifications/Server/ForceEnabled.php b/app/Notifications/Server/ForceEnabled.php new file mode 100644 index 000000000..c29a08644 --- /dev/null +++ b/app/Notifications/Server/ForceEnabled.php @@ -0,0 +1,63 @@ +subject("Coolify: Server ({$this->server->name}) enabled again!"); + $mail->view('emails.server-force-enabled', [ + 'name' => $this->server->name, + ]); + return $mail; + } + + public function toDiscord(): string + { + $message = "Coolify: Server ({$this->server->name}) enabled again!"; + return $message; + } + public function toTelegram(): array + { + return [ + "message" => "Coolify: Server ({$this->server->name}) enabled again!" + ]; + } +} diff --git a/app/Traits/ExecuteRemoteCommand.php b/app/Traits/ExecuteRemoteCommand.php index 529dacd7a..9b34fabae 100644 --- a/app/Traits/ExecuteRemoteCommand.php +++ b/app/Traits/ExecuteRemoteCommand.php @@ -24,6 +24,12 @@ public function execute_remote_command(...$commands) if ($this->server instanceof Server === false) { throw new \RuntimeException('Server is not set or is not an instance of Server model'); } + if ($this->server->settings->force_disabled) { + $this->application_deployment_queue->update([ + 'status' => ApplicationDeploymentStatus::FAILED->value, + ]); + throw new \RuntimeException('Server is disabled'); + } $commandsText->each(function ($single_command) { $command = data_get($single_command, 'command') ?? $single_command[0] ?? null; if ($command === null) { diff --git a/database/migrations/2024_02_25_222150_add_disabled_server_due_to_overflow.php b/database/migrations/2024_02_25_222150_add_server_force_disabled_field.php similarity index 80% rename from database/migrations/2024_02_25_222150_add_disabled_server_due_to_overflow.php rename to database/migrations/2024_02_25_222150_add_server_force_disabled_field.php index 3d1b808ab..8509a9909 100644 --- a/database/migrations/2024_02_25_222150_add_disabled_server_due_to_overflow.php +++ b/database/migrations/2024_02_25_222150_add_server_force_disabled_field.php @@ -12,7 +12,7 @@ public function up(): void { Schema::table('server_settings', function (Blueprint $table) { - $table->boolean('disabled_by_overflow')->default(false); + $table->boolean('force_disabled')->default(false); }); } @@ -22,7 +22,7 @@ public function up(): void public function down(): void { Schema::table('server_settings', function (Blueprint $table) { - $table->dropColumn('disabled_by_overflow'); + $table->dropColumn('force_disabled'); }); } }; diff --git a/resources/views/components/server/sidebar.blade.php b/resources/views/components/server/sidebar.blade.php index 86bb92a87..a163bf05f 100644 --- a/resources/views/components/server/sidebar.blade.php +++ b/resources/views/components/server/sidebar.blade.php @@ -1,24 +1,18 @@ -