mirror of
https://github.com/coollabsio/coolify.git
synced 2026-11-06 21:18:11 -04:00
fix(settings): load instance backup page without a backup schedule
/settings/backup returned 500 when the coolify-db resource existed without a scheduled backup. Configure backup now reuses the existing coolify-db and creates only the missing schedule for the root team, without forcing id 0. Closes #12074
This commit is contained in:
@@ -257,10 +257,8 @@ class Init extends Command
|
||||
$database = StandalonePostgresql::withTrashed()->find(0);
|
||||
if ($database && $database->trashed()) {
|
||||
$database->restore();
|
||||
$scheduledBackup = ScheduledDatabaseBackup::find(0);
|
||||
if (! $scheduledBackup) {
|
||||
if (! $database->scheduledBackups()->exists()) {
|
||||
ScheduledDatabaseBackup::create([
|
||||
'id' => 0,
|
||||
'enabled' => true,
|
||||
'save_s3' => false,
|
||||
'frequency' => '0 0 * * *',
|
||||
|
||||
@@ -71,7 +71,7 @@ class SettingsBackup extends Component
|
||||
$this->backup->enabled = false;
|
||||
$this->backup->save();
|
||||
}
|
||||
$this->executions = $this->backup->executions;
|
||||
$this->executions = $this->backup?->executions ?? [];
|
||||
}
|
||||
$this->settings = $settings;
|
||||
$this->s3s = $s3s;
|
||||
@@ -81,44 +81,46 @@ class SettingsBackup extends Component
|
||||
{
|
||||
try {
|
||||
$this->authorize('update', $this->settings);
|
||||
$server = Server::findOrFail(0);
|
||||
$out = instant_remote_process(['docker inspect coolify-db'], $server);
|
||||
$envs = format_docker_envs_to_json($out);
|
||||
$postgres_password = $envs['POSTGRES_PASSWORD'];
|
||||
$postgres_user = $envs['POSTGRES_USER'];
|
||||
$postgres_db = $envs['POSTGRES_DB'];
|
||||
$this->database = new StandalonePostgresql;
|
||||
$this->database->forceFill([
|
||||
'id' => 0,
|
||||
'name' => 'coolify-db',
|
||||
'description' => 'Coolify database',
|
||||
'postgres_user' => $postgres_user,
|
||||
'postgres_password' => $postgres_password,
|
||||
'postgres_db' => $postgres_db,
|
||||
'status' => 'running',
|
||||
'destination_type' => StandaloneDocker::class,
|
||||
'destination_id' => 0,
|
||||
]);
|
||||
$this->database->save();
|
||||
$this->backup = ScheduledDatabaseBackup::create([
|
||||
'id' => 0,
|
||||
'enabled' => true,
|
||||
'save_s3' => false,
|
||||
'frequency' => '0 0 * * *',
|
||||
'database_id' => $this->database->id,
|
||||
'database_type' => StandalonePostgresql::class,
|
||||
'team_id' => currentTeam()->id,
|
||||
]);
|
||||
$this->database = StandalonePostgresql::whereName('coolify-db')->first();
|
||||
if (! $this->database) {
|
||||
$server = Server::findOrFail(0);
|
||||
$out = instant_remote_process(['docker inspect coolify-db'], $server);
|
||||
$envs = format_docker_envs_to_json($out);
|
||||
$this->database = new StandalonePostgresql;
|
||||
$this->database->forceFill([
|
||||
'id' => 0,
|
||||
'name' => 'coolify-db',
|
||||
'description' => 'Coolify database',
|
||||
'postgres_user' => $envs['POSTGRES_USER'],
|
||||
'postgres_password' => $envs['POSTGRES_PASSWORD'],
|
||||
'postgres_db' => $envs['POSTGRES_DB'],
|
||||
'status' => 'running',
|
||||
'destination_type' => StandaloneDocker::class,
|
||||
'destination_id' => 0,
|
||||
]);
|
||||
$this->database->save();
|
||||
}
|
||||
$this->backup = $this->database->scheduledBackups()->first()
|
||||
?? ScheduledDatabaseBackup::create([
|
||||
'enabled' => true,
|
||||
'save_s3' => false,
|
||||
'frequency' => '0 0 * * *',
|
||||
'database_id' => $this->database->id,
|
||||
'database_type' => StandalonePostgresql::class,
|
||||
'team_id' => 0,
|
||||
]);
|
||||
$this->database->refresh();
|
||||
$this->backup->refresh();
|
||||
auditLog('ui.database.backup_schedule_created', [
|
||||
'team_id' => $this->backup->team_id,
|
||||
'database_uuid' => $this->database->uuid,
|
||||
'database_name' => $this->database->name,
|
||||
'backup_uuid' => $this->backup->uuid,
|
||||
'frequency' => $this->backup->frequency,
|
||||
'save_s3' => (bool) $this->backup->save_s3,
|
||||
]);
|
||||
if ($this->backup->wasRecentlyCreated) {
|
||||
auditLog('ui.database.backup_schedule_created', [
|
||||
'team_id' => $this->backup->team_id,
|
||||
'database_uuid' => $this->database->uuid,
|
||||
'database_name' => $this->database->name,
|
||||
'backup_uuid' => $this->backup->uuid,
|
||||
'frequency' => $this->backup->frequency,
|
||||
'save_s3' => (bool) $this->backup->save_s3,
|
||||
]);
|
||||
}
|
||||
$this->s3s = S3Storage::whereTeamId(0)->get();
|
||||
|
||||
$this->uuid = $this->database->uuid;
|
||||
|
||||
@@ -2,11 +2,15 @@
|
||||
|
||||
use App\Livewire\SettingsBackup;
|
||||
use App\Models\InstanceSettings;
|
||||
use App\Models\ScheduledDatabaseBackup;
|
||||
use App\Models\Server;
|
||||
use App\Models\StandaloneDocker;
|
||||
use App\Models\StandalonePostgresql;
|
||||
use App\Models\Team;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Facades\Blade;
|
||||
use Illuminate\Support\Facades\Process;
|
||||
use Illuminate\Support\Once;
|
||||
use Livewire\Livewire;
|
||||
|
||||
@@ -84,3 +88,76 @@ test('instance backup settings show a configure button when backup is not set up
|
||||
->assertSee('Configure backup')
|
||||
->assertSeeHtml('wire:click="addCoolifyDatabase"');
|
||||
});
|
||||
|
||||
function settingsBackupInstanceDatabaseWithoutSchedule(): StandalonePostgresql
|
||||
{
|
||||
Server::flushIdentityMap();
|
||||
$rootTeam = Team::find(0) ?? Team::factory()->create(['id' => 0]);
|
||||
$server = Server::factory()->create([
|
||||
'id' => 0,
|
||||
'team_id' => $rootTeam->id,
|
||||
'ip' => '127.0.0.1',
|
||||
]);
|
||||
$server->settings()->update([
|
||||
'is_reachable' => true,
|
||||
'is_usable' => true,
|
||||
'force_disabled' => false,
|
||||
]);
|
||||
StandaloneDocker::query()->where('server_id', $server->id)->firstOrFail()->forceFill(['id' => 0])->save();
|
||||
InstanceSettings::forceCreate(['id' => 0]);
|
||||
Once::flush();
|
||||
|
||||
$database = new StandalonePostgresql;
|
||||
$database->forceFill([
|
||||
'id' => 0,
|
||||
'name' => 'coolify-db',
|
||||
'description' => 'Coolify database',
|
||||
'postgres_user' => 'coolify',
|
||||
'postgres_password' => 'password',
|
||||
'postgres_db' => 'coolify',
|
||||
'status' => 'running',
|
||||
'destination_type' => StandaloneDocker::class,
|
||||
'destination_id' => 0,
|
||||
]);
|
||||
$database->save();
|
||||
|
||||
$user = User::factory()->create();
|
||||
$rootTeam->members()->attach($user->id, ['role' => 'admin']);
|
||||
test()->actingAs($user);
|
||||
session(['currentTeam' => ['id' => $rootTeam->id]]);
|
||||
|
||||
return $database;
|
||||
}
|
||||
|
||||
test('instance backup settings render when the instance database has no backup schedule', function () {
|
||||
settingsBackupInstanceDatabaseWithoutSchedule();
|
||||
|
||||
Livewire::test(SettingsBackup::class)
|
||||
->assertOk()
|
||||
->assertSet('executions', [])
|
||||
->assertSee('Backup is not configured')
|
||||
->assertSee('Configure backup');
|
||||
});
|
||||
|
||||
test('configure backup creates only the missing schedule for an existing instance database', function () {
|
||||
$database = settingsBackupInstanceDatabaseWithoutSchedule();
|
||||
$otherTeam = Team::factory()->create();
|
||||
auth()->user()->teams()->attach($otherTeam->id, ['role' => 'owner']);
|
||||
session(['currentTeam' => ['id' => $otherTeam->id]]);
|
||||
Process::fake();
|
||||
|
||||
Livewire::test(SettingsBackup::class)
|
||||
->call('addCoolifyDatabase')
|
||||
->assertHasNoErrors()
|
||||
->assertSee('Instance database');
|
||||
|
||||
Process::assertNothingRan();
|
||||
$backup = $database->scheduledBackups()->sole();
|
||||
|
||||
expect(StandalonePostgresql::query()->where('name', 'coolify-db')->count())->toBe(1)
|
||||
->and($backup->id)->not->toBe(0)
|
||||
->and($backup->team_id)->toBe(0)
|
||||
->and($backup->enabled)->toBeTruthy()
|
||||
->and($backup->frequency)->toBe('0 0 * * *')
|
||||
->and(ScheduledDatabaseBackup::query()->count())->toBe(1);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user