mirror of
https://github.com/tiennm99/coolify.git
synced 2026-10-14 14:17:18 +00:00
feat(service): unify database and storage backups on one page
List service database schedules with volume backups, add a database picker when creating scheduled DB backups from the service page, and cover the unified table and create flow in tests.
This commit is contained in:
1 parent
12b14665b5
commit
c0b75d04a6
8 files changed
+288
-51
No files matched your search
@@ -94,6 +94,36 @@ it('creates a service database backup without S3 and opens its configuration', f
|
||||
->and($backup->s3_storage_id)->toBeNull();
|
||||
});
|
||||
|
||||
it('selects a service database when creating a backup from the unified backups page', function () {
|
||||
$service = Service::factory()->create([
|
||||
'server_id' => $this->server->id,
|
||||
'destination_id' => $this->destination->id,
|
||||
'destination_type' => $this->destination->getMorphClass(),
|
||||
'environment_id' => $this->environment->id,
|
||||
]);
|
||||
ServiceDatabase::create([
|
||||
'service_id' => $service->id,
|
||||
'name' => 'primary',
|
||||
'image' => 'postgres:16-alpine',
|
||||
'custom_type' => 'postgresql',
|
||||
]);
|
||||
$analytics = ServiceDatabase::create([
|
||||
'service_id' => $service->id,
|
||||
'name' => 'analytics',
|
||||
'image' => 'postgres:16-alpine',
|
||||
'custom_type' => 'postgresql',
|
||||
]);
|
||||
|
||||
Livewire::test(CreateScheduledBackup::class, ['service' => $service])
|
||||
->assertSee('Database')
|
||||
->assertSee('analytics')
|
||||
->set('selectedDatabaseUuid', $analytics->uuid)
|
||||
->set('frequency', 'daily')
|
||||
->call('submit');
|
||||
|
||||
expect(ScheduledDatabaseBackup::query()->sole()->database->is($analytics))->toBeTrue();
|
||||
});
|
||||
|
||||
it('creates a clickhouse backup for its configured database', function () {
|
||||
$server = Server::factory()->create(['team_id' => $this->team->id]);
|
||||
$destination = StandaloneDocker::where('server_id', $server->id)->firstOrFail();
|
||||
|
||||
@@ -80,13 +80,35 @@ it('shows the service sidebar on the storage backups page', function () {
|
||||
->toContain('xl:grid-cols-[210px_minmax(0,1fr)]');
|
||||
});
|
||||
|
||||
it('links compose database backups to the parent service backups page', function () {
|
||||
it('combines service database and storage backups in one section', function () {
|
||||
$backups = file_get_contents(resource_path('views/livewire/project/service/volume-backup/index.blade.php'));
|
||||
$styles = file_get_contents(resource_path('css/app.css'));
|
||||
|
||||
expect(substr_count($backups, '<x-application.settings-section '))->toBe(1)
|
||||
->and(substr_count($backups, 'data-table-header backup-table-grid'))->toBe(1)
|
||||
->and($backups)->toContain('Storage backup')->toContain('Database backup')
|
||||
->not->toContain('data-table-header scheduled-backups-table-grid')
|
||||
->not->toContain('>Database backups</h3>')
|
||||
->not->toContain('>Storage backups</h3>')
|
||||
->toContain("'application-settings-section-body w-full'")
|
||||
->toContain('class="data-table w-full overflow-x-auto"')
|
||||
->toContain('backup-table-grid service-backup-table-grid')
|
||||
->not->toContain('<span class="text-right">Executions</span>')
|
||||
->toContain('class="data-table-row backup-table-grid text-[13px]')
|
||||
->toContain('class="listbox-option justify-start! gap-2.5!"')
|
||||
->toContain('x-data="{ dropdownOpen: false }"')
|
||||
->toContain('class="listbox-panel left-0! right-auto! z-[90]! w-52! min-w-52! sm:left-auto! sm:right-0!"')
|
||||
->not->toContain('<x-dropdown');
|
||||
|
||||
expect($styles)->toContain('.service-backup-table-grid');
|
||||
});
|
||||
|
||||
it('links compose database backups to the unified service backups page', function () {
|
||||
$sidebar = file_get_contents(resource_path('views/components/service-database/sidebar.blade.php'));
|
||||
|
||||
expect($sidebar)
|
||||
->toContain("'route' => 'project.service.volume-backups.index'")
|
||||
->toContain("'parameters' => \$serviceParameters")
|
||||
->toContain("\$item['parameters'] ?? \$parameters")
|
||||
->not->toContain("'route' => 'project.service.database.backups'");
|
||||
});
|
||||
|
||||
|
||||
@@ -202,3 +202,38 @@ test('service database backup schedules use dedicated general retention and exec
|
||||
->assertDontSee('Number of backups to keep')
|
||||
->assertDontSee('Cleanup Failed Backups');
|
||||
});
|
||||
|
||||
test('service storage backups page includes schedules from all compose databases', function () {
|
||||
$secondDatabase = ServiceDatabase::create([
|
||||
'service_id' => $this->ownService->id,
|
||||
'name' => 'analytics-db',
|
||||
'image' => 'postgres:16-alpine',
|
||||
'custom_type' => 'postgresql',
|
||||
]);
|
||||
|
||||
foreach ([$this->ownServiceDatabase, $secondDatabase] as $database) {
|
||||
ScheduledDatabaseBackup::create([
|
||||
'team_id' => $this->teamA->id,
|
||||
'description' => $database->name.' backup',
|
||||
'frequency' => 'daily',
|
||||
'database_id' => $database->id,
|
||||
'database_type' => $database->getMorphClass(),
|
||||
]);
|
||||
}
|
||||
|
||||
$this->get(route('project.service.volume-backups.index', [
|
||||
'project_uuid' => $this->projectA->uuid,
|
||||
'environment_uuid' => $this->environmentA->uuid,
|
||||
'service_uuid' => $this->ownService->uuid,
|
||||
]))
|
||||
->assertOk()
|
||||
->assertSee('>Database</span>', false)
|
||||
->assertSee('own-db')
|
||||
->assertSee('analytics-db')
|
||||
->assertSee(route('project.service.database.backups', [
|
||||
'project_uuid' => $this->projectA->uuid,
|
||||
'environment_uuid' => $this->environmentA->uuid,
|
||||
'service_uuid' => $this->ownService->uuid,
|
||||
'stack_service_uuid' => $this->ownServiceDatabase->uuid,
|
||||
]), false);
|
||||
});
|
||||
Reference in new issue
Block a user