fix(backups): redirect to executions after manual backup queueing
Queue manual database and volume backups before redirecting to their execution views, including schedules with unusable S3 storage.
This commit is contained in:
parent
d7385ad0c4
commit
41eee14bd3
4 changed files with 111 additions and 7 deletions
|
|
@ -206,6 +206,25 @@ public function backupNow()
|
|||
|
||||
DatabaseBackupJob::dispatch($this->backup);
|
||||
$this->dispatch('success', 'Backup queued. It will be available in a few minutes.');
|
||||
|
||||
$database = $this->backup->database;
|
||||
|
||||
if ($database instanceof ServiceDatabase) {
|
||||
return redirect()->route('project.service.database.backup.executions', [
|
||||
'project_uuid' => $database->service->project()->uuid,
|
||||
'environment_uuid' => $database->service->environment->uuid,
|
||||
'service_uuid' => $database->service->uuid,
|
||||
'stack_service_uuid' => $database->uuid,
|
||||
'backup_uuid' => $this->backup->uuid,
|
||||
]);
|
||||
}
|
||||
|
||||
return redirect()->route('project.database.backup.executions', [
|
||||
'project_uuid' => $database->project()->uuid,
|
||||
'environment_uuid' => $database->environment->uuid,
|
||||
'database_uuid' => $database->uuid,
|
||||
'backup_uuid' => $this->backup->uuid,
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -178,21 +178,28 @@ public function toggleEnabled(): void
|
|||
$this->dispatch('success', $this->enabled ? 'Storage backups enabled.' : 'Storage backups disabled.');
|
||||
}
|
||||
|
||||
public function backupNow(): void
|
||||
public function backupNow()
|
||||
{
|
||||
$this->authorize('update', $this->resource);
|
||||
|
||||
if (! $this->validateSettings()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (! $this->backup) {
|
||||
if (! $this->validateSettings()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->enabled = false;
|
||||
$this->backup = $this->persistBackup(false);
|
||||
}
|
||||
|
||||
$this->backup = $this->persistBackup($this->enabled);
|
||||
VolumeBackupJob::dispatch($this->backup);
|
||||
$this->dispatch('success', 'Storage backup queued.');
|
||||
|
||||
return redirect()->route('project.application.backup.executions', [
|
||||
'project_uuid' => $this->resource->project()->uuid,
|
||||
'environment_uuid' => $this->resource->environment->uuid,
|
||||
'application_uuid' => $this->resource->uuid,
|
||||
'backup_uuid' => $this->backup->uuid,
|
||||
]);
|
||||
}
|
||||
|
||||
public function delete(?string $password = null, array $selectedActions = [])
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<?php
|
||||
|
||||
use App\Jobs\DatabaseBackupJob;
|
||||
use App\Livewire\Project\Database\BackupEdit;
|
||||
use App\Models\Environment;
|
||||
use App\Models\InstanceSettings;
|
||||
|
|
@ -12,6 +13,7 @@
|
|||
use App\Models\Team;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Facades\Queue;
|
||||
use Livewire\Livewire;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
|
@ -226,6 +228,40 @@ function createS3StorageForBackupEditValidationTest(Team|int $team, string $name
|
|||
expect($backup->refresh()->enabled)->toBeFalsy();
|
||||
});
|
||||
|
||||
it('redirects to executions after queuing a database backup with unusable S3 storage', function () {
|
||||
Queue::fake();
|
||||
$s3Storage = createS3StorageForBackupEditValidationTest($this->team, 'Unavailable storage');
|
||||
$s3Storage->update(['is_usable' => false]);
|
||||
$backup = createBackupForEditValidationTest($this->team, [
|
||||
'enabled' => true,
|
||||
's3_storage_id' => $s3Storage->id,
|
||||
'database_backup_retention_amount_locally' => 7,
|
||||
'database_backup_retention_days_locally' => 0,
|
||||
'database_backup_retention_max_storage_locally' => 0,
|
||||
'database_backup_retention_amount_s3' => 7,
|
||||
'database_backup_retention_days_s3' => 0,
|
||||
'database_backup_retention_max_storage_s3' => 0,
|
||||
'dump_all' => false,
|
||||
'timeout' => 3600,
|
||||
]);
|
||||
$database = $backup->database;
|
||||
$parameters = [
|
||||
'project_uuid' => $database->project()->uuid,
|
||||
'environment_uuid' => $database->environment->uuid,
|
||||
'database_uuid' => $database->uuid,
|
||||
'backup_uuid' => $backup->uuid,
|
||||
];
|
||||
|
||||
Livewire::test(BackupEdit::class, [
|
||||
'backup' => $backup,
|
||||
'availableS3Storages' => $this->team->s3s,
|
||||
])
|
||||
->call('backupNow')
|
||||
->assertRedirectToRoute('project.database.backup.executions', $parameters);
|
||||
|
||||
Queue::assertPushed(DatabaseBackupJob::class);
|
||||
});
|
||||
|
||||
it('disables S3 backup when saved without a selected S3 storage', function () {
|
||||
$backup = createBackupForEditValidationTest($this->team);
|
||||
|
||||
|
|
|
|||
|
|
@ -1008,16 +1008,58 @@ function signInForVolumeBackups($testCase, Team $team): User
|
|||
signInForVolumeBackups($this, $team);
|
||||
[$application, $volume] = createVolumeBackupApplication($team);
|
||||
|
||||
Livewire::test(VolumeBackups::class, ['storage' => $volume, 'resource' => $application])
|
||||
$component = Livewire::test(VolumeBackups::class, ['storage' => $volume, 'resource' => $application])
|
||||
->call('backupNow')
|
||||
->assertDispatched('success');
|
||||
|
||||
$backup = ScheduledVolumeBackup::query()->sole();
|
||||
|
||||
$component->assertRedirectToRoute('project.application.backup.executions', [
|
||||
'project_uuid' => $application->project()->uuid,
|
||||
'environment_uuid' => $application->environment->uuid,
|
||||
'application_uuid' => $application->uuid,
|
||||
'backup_uuid' => $backup->uuid,
|
||||
]);
|
||||
|
||||
expect($backup->enabled)->toBeFalse();
|
||||
Queue::assertPushed(VolumeBackupJob::class, fn (VolumeBackupJob $job) => $job->backup->is($backup));
|
||||
});
|
||||
|
||||
it('queues a manual backup when its S3 storage has become unusable', function () {
|
||||
Queue::fake();
|
||||
$team = Team::factory()->create();
|
||||
signInForVolumeBackups($this, $team);
|
||||
[$application, $volume] = createVolumeBackupApplication($team);
|
||||
$s3Storage = S3Storage::create([
|
||||
'name' => 'Unavailable storage',
|
||||
'region' => 'us-east-1',
|
||||
'key' => 'key',
|
||||
'secret' => 'secret',
|
||||
'bucket' => 'bucket',
|
||||
'endpoint' => 'https://s3.example.com',
|
||||
'team_id' => $team->id,
|
||||
'is_usable' => false,
|
||||
]);
|
||||
$backup = $volume->scheduledBackups()->create([
|
||||
'team_id' => $team->id,
|
||||
's3_storage_id' => $s3Storage->id,
|
||||
'frequency' => 'daily',
|
||||
'save_s3' => true,
|
||||
]);
|
||||
$parameters = [
|
||||
'project_uuid' => $application->project()->uuid,
|
||||
'environment_uuid' => $application->environment->uuid,
|
||||
'application_uuid' => $application->uuid,
|
||||
'backup_uuid' => $backup->uuid,
|
||||
];
|
||||
|
||||
Livewire::test(VolumeBackups::class, ['storage' => $volume, 'resource' => $application])
|
||||
->call('backupNow')
|
||||
->assertRedirectToRoute('project.application.backup.executions', $parameters);
|
||||
|
||||
Queue::assertPushed(VolumeBackupJob::class, fn (VolumeBackupJob $job) => $job->backup->is($backup));
|
||||
});
|
||||
|
||||
it('deletes local archives before deleting a volume backup schedule', function () {
|
||||
Process::fake();
|
||||
$team = Team::factory()->create();
|
||||
|
|
|
|||
Loading…
Reference in a new issue