fix: pull helper image on helper_version change
This commit is contained in:
		@@ -3,11 +3,11 @@
 | 
				
			|||||||
namespace App\Console;
 | 
					namespace App\Console;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use App\Jobs\CheckForUpdatesJob;
 | 
					use App\Jobs\CheckForUpdatesJob;
 | 
				
			||||||
 | 
					use App\Jobs\CheckHelperImageJob;
 | 
				
			||||||
use App\Jobs\CleanupInstanceStuffsJob;
 | 
					use App\Jobs\CleanupInstanceStuffsJob;
 | 
				
			||||||
use App\Jobs\CleanupStaleMultiplexedConnections;
 | 
					use App\Jobs\CleanupStaleMultiplexedConnections;
 | 
				
			||||||
use App\Jobs\DatabaseBackupJob;
 | 
					use App\Jobs\DatabaseBackupJob;
 | 
				
			||||||
use App\Jobs\DockerCleanupJob;
 | 
					use App\Jobs\DockerCleanupJob;
 | 
				
			||||||
use App\Jobs\PullHelperImageJob;
 | 
					 | 
				
			||||||
use App\Jobs\PullSentinelImageJob;
 | 
					use App\Jobs\PullSentinelImageJob;
 | 
				
			||||||
use App\Jobs\PullTemplatesFromCDN;
 | 
					use App\Jobs\PullTemplatesFromCDN;
 | 
				
			||||||
use App\Jobs\ScheduledTaskJob;
 | 
					use App\Jobs\ScheduledTaskJob;
 | 
				
			||||||
@@ -44,7 +44,7 @@ class Kernel extends ConsoleKernel
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            $schedule->command('telescope:prune')->daily();
 | 
					            $schedule->command('telescope:prune')->daily();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $schedule->job(new PullHelperImageJob)->everyFiveMinutes()->onOneServer();
 | 
					            $schedule->job(new CheckHelperImageJob)->everyFiveMinutes()->onOneServer();
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            // Instance Jobs
 | 
					            // Instance Jobs
 | 
				
			||||||
            $schedule->command('horizon:snapshot')->everyFiveMinutes();
 | 
					            $schedule->command('horizon:snapshot')->everyFiveMinutes();
 | 
				
			||||||
@@ -80,7 +80,7 @@ class Kernel extends ConsoleKernel
 | 
				
			|||||||
                })->cron($settings->update_check_frequency)->timezone($settings->instance_timezone)->onOneServer();
 | 
					                })->cron($settings->update_check_frequency)->timezone($settings->instance_timezone)->onOneServer();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        $schedule->job(new PullHelperImageJob)
 | 
					        $schedule->job(new CheckHelperImageJob)
 | 
				
			||||||
            ->cron($settings->update_check_frequency)
 | 
					            ->cron($settings->update_check_frequency)
 | 
				
			||||||
            ->timezone($settings->instance_timezone)
 | 
					            ->timezone($settings->instance_timezone)
 | 
				
			||||||
            ->onOneServer();
 | 
					            ->onOneServer();
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										41
									
								
								app/Jobs/CheckHelperImageJob.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								app/Jobs/CheckHelperImageJob.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Jobs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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\Facades\Http;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CheckHelperImageJob implements ShouldBeEncrypted, ShouldQueue
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public $timeout = 1000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function __construct() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function handle(): void
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            $response = Http::retry(3, 1000)->get('https://cdn.coollabs.io/coolify/versions.json');
 | 
				
			||||||
 | 
					            if ($response->successful()) {
 | 
				
			||||||
 | 
					                $versions = $response->json();
 | 
				
			||||||
 | 
					                $settings = instanceSettings();
 | 
				
			||||||
 | 
					                $latest_version = data_get($versions, 'coolify.helper.version');
 | 
				
			||||||
 | 
					                $current_version = $settings->helper_version;
 | 
				
			||||||
 | 
					                if (version_compare($latest_version, $current_version, '>')) {
 | 
				
			||||||
 | 
					                    $settings->update(['helper_version' => $latest_version]);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        } catch (\Throwable $e) {
 | 
				
			||||||
 | 
					            send_internal_notification('CheckHelperImageJob failed with: '.$e->getMessage());
 | 
				
			||||||
 | 
					            throw $e;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -504,8 +504,6 @@ class DatabaseBackupJob implements ShouldBeEncrypted, ShouldQueue
 | 
				
			|||||||
                $network = $this->database->destination->network;
 | 
					                $network = $this->database->destination->network;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $this->ensureHelperImageAvailable();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            $fullImageName = $this->getFullImageName();
 | 
					            $fullImageName = $this->getFullImageName();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (isDev()) {
 | 
					            if (isDev()) {
 | 
				
			||||||
@@ -538,35 +536,6 @@ class DatabaseBackupJob implements ShouldBeEncrypted, ShouldQueue
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private function ensureHelperImageAvailable(): void
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $fullImageName = $this->getFullImageName();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $imageExists = $this->checkImageExists($fullImageName);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (! $imageExists) {
 | 
					 | 
				
			||||||
            $this->pullHelperImage($fullImageName);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private function checkImageExists(string $fullImageName): bool
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $result = instant_remote_process(["docker image inspect {$fullImageName} >/dev/null 2>&1 && echo 'exists' || echo 'not exists'"], $this->server, false);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return trim($result) === 'exists';
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private function pullHelperImage(string $fullImageName): void
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        try {
 | 
					 | 
				
			||||||
            instant_remote_process(["docker pull {$fullImageName}"], $this->server);
 | 
					 | 
				
			||||||
        } catch (\Exception $e) {
 | 
					 | 
				
			||||||
            $errorMessage = 'Failed to pull helper image: '.$e->getMessage();
 | 
					 | 
				
			||||||
            $this->add_to_backup_output($errorMessage);
 | 
					 | 
				
			||||||
            throw new \RuntimeException($errorMessage);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private function getFullImageName(): string
 | 
					    private function getFullImageName(): string
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $settings = instanceSettings();
 | 
					        $settings = instanceSettings();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,7 +9,6 @@ use Illuminate\Contracts\Queue\ShouldQueue;
 | 
				
			|||||||
use Illuminate\Foundation\Bus\Dispatchable;
 | 
					use Illuminate\Foundation\Bus\Dispatchable;
 | 
				
			||||||
use Illuminate\Queue\InteractsWithQueue;
 | 
					use Illuminate\Queue\InteractsWithQueue;
 | 
				
			||||||
use Illuminate\Queue\SerializesModels;
 | 
					use Illuminate\Queue\SerializesModels;
 | 
				
			||||||
use Illuminate\Support\Facades\Http;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
class PullHelperImageJob implements ShouldBeEncrypted, ShouldQueue
 | 
					class PullHelperImageJob implements ShouldBeEncrypted, ShouldQueue
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -17,28 +16,15 @@ class PullHelperImageJob implements ShouldBeEncrypted, ShouldQueue
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public $timeout = 1000;
 | 
					    public $timeout = 1000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function __construct() {}
 | 
					    public function __construct(public Server $server) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function handle(): void
 | 
					    public function handle(): void
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            $response = Http::retry(3, 1000)->get('https://cdn.coollabs.io/coolify/versions.json');
 | 
					            $helperImage = config('coolify.helper_image');
 | 
				
			||||||
            if ($response->successful()) {
 | 
					            $latest_version = instanceSettings()->helper_version;
 | 
				
			||||||
                $versions = $response->json();
 | 
					            instant_remote_process(["docker pull -q {$helperImage}:{$latest_version}"], $this->server, false);
 | 
				
			||||||
                $settings = instanceSettings();
 | 
					 | 
				
			||||||
                $latest_version = data_get($versions, 'coolify.helper.version');
 | 
					 | 
				
			||||||
                $current_version = $settings->helper_version;
 | 
					 | 
				
			||||||
                if (version_compare($latest_version, $current_version, '>')) {
 | 
					 | 
				
			||||||
                    // New version available
 | 
					 | 
				
			||||||
                    // $helperImage = config('coolify.helper_image');
 | 
					 | 
				
			||||||
                    // instant_remote_process(["docker pull -q {$helperImage}:{$latest_version}"], $this->server);
 | 
					 | 
				
			||||||
                    $settings->update(['helper_version' => $latest_version]);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        } catch (\Throwable $e) {
 | 
					        } catch (\Throwable $e) {
 | 
				
			||||||
            send_internal_notification('PullHelperImageJob failed with: '.$e->getMessage());
 | 
					 | 
				
			||||||
            ray($e->getMessage());
 | 
					 | 
				
			||||||
            throw $e;
 | 
					            throw $e;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace App\Models;
 | 
					namespace App\Models;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Jobs\PullHelperImageJob;
 | 
				
			||||||
use App\Notifications\Channels\SendsEmail;
 | 
					use App\Notifications\Channels\SendsEmail;
 | 
				
			||||||
use Illuminate\Database\Eloquent\Casts\Attribute;
 | 
					use Illuminate\Database\Eloquent\Casts\Attribute;
 | 
				
			||||||
use Illuminate\Database\Eloquent\Model;
 | 
					use Illuminate\Database\Eloquent\Model;
 | 
				
			||||||
@@ -24,6 +25,20 @@ class InstanceSettings extends Model implements SendsEmail
 | 
				
			|||||||
        'sentinel_token' => 'encrypted',
 | 
					        'sentinel_token' => 'encrypted',
 | 
				
			||||||
    ];
 | 
					    ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected static function booted(): void
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        static::updated(function ($settings) {
 | 
				
			||||||
 | 
					            if ($settings->isDirty('helper_version')) {
 | 
				
			||||||
 | 
					                Server::chunkById(100, function ($servers) {
 | 
				
			||||||
 | 
					                    foreach ($servers as $server) {
 | 
				
			||||||
 | 
					                        PullHelperImageJob::dispatch($server);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function fqdn(): Attribute
 | 
					    public function fqdn(): Attribute
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return Attribute::make(
 | 
					        return Attribute::make(
 | 
				
			||||||
@@ -87,16 +102,4 @@ class InstanceSettings extends Model implements SendsEmail
 | 
				
			|||||||
        return "[{$instanceName}]";
 | 
					        return "[{$instanceName}]";
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function helperVersion(): Attribute
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        return Attribute::make(
 | 
					 | 
				
			||||||
            get: function ($value) {
 | 
					 | 
				
			||||||
                if (isDev()) {
 | 
					 | 
				
			||||||
                    return 'latest';
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                return $value;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user