mirror of
https://github.com/tiennm99/coolify.git
synced 2026-10-11 03:13:17 +00:00
feat(backups): support scheduled backups for application storage targets
Add polymorphic volume backup scheduling for persistent volumes and directories, expose schedule management via API, and reorganize backup configuration and execution views.
This commit is contained in:
1 parent
995ec5fbb6
commit
d7385ad0c4
60 files changed
+3570
-985
No files matched your search
@@ -20,6 +20,7 @@ use App\Http\Controllers\Api\ServiceDatabasesController;
|
||||
use App\Http\Controllers\Api\ServicesController;
|
||||
use App\Http\Controllers\Api\TagsController;
|
||||
use App\Http\Controllers\Api\TeamController;
|
||||
use App\Http\Controllers\Api\VolumeBackupsController;
|
||||
use App\Http\Controllers\Api\VultrController;
|
||||
use App\Http\Middleware\ApiAllowed;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
@@ -150,6 +151,9 @@ Route::group([
|
||||
Route::post('/applications/{uuid}/storages', [ApplicationsController::class, 'create_storage'])->middleware(['api.ability:write']);
|
||||
Route::patch('/applications/{uuid}/storages', [ApplicationsController::class, 'update_storage'])->middleware(['api.ability:write']);
|
||||
Route::delete('/applications/{uuid}/storages/{storage_uuid}', [ApplicationsController::class, 'delete_storage'])->middleware(['api.ability:write']);
|
||||
Route::put('/applications/{uuid}/storages/{storage_uuid}/backups', [VolumeBackupsController::class, 'upsert'])
|
||||
->defaults('resource_type', 'application')
|
||||
->middleware(['api.ability:write']);
|
||||
|
||||
Route::get('/applications/{uuid}/tags', [ApplicationsController::class, 'tags'])->middleware(['api.ability:read']);
|
||||
Route::post('/applications/{uuid}/tags', [ApplicationsController::class, 'create_tag'])->middleware(['api.ability:write']);
|
||||
@@ -194,6 +198,9 @@ Route::group([
|
||||
Route::post('/databases/{uuid}/storages', [DatabasesController::class, 'create_storage'])->middleware(['api.ability:write']);
|
||||
Route::patch('/databases/{uuid}/storages', [DatabasesController::class, 'update_storage'])->middleware(['api.ability:write']);
|
||||
Route::delete('/databases/{uuid}/storages/{storage_uuid}', [DatabasesController::class, 'delete_storage'])->middleware(['api.ability:write']);
|
||||
Route::put('/databases/{uuid}/storages/{storage_uuid}/backups', [VolumeBackupsController::class, 'upsert'])
|
||||
->defaults('resource_type', 'database')
|
||||
->middleware(['api.ability:write']);
|
||||
|
||||
Route::get('/databases/{uuid}/envs', [DatabasesController::class, 'envs'])->middleware(['api.ability:read']);
|
||||
Route::post('/databases/{uuid}/envs', [DatabasesController::class, 'create_env'])->middleware(['api.ability:write']);
|
||||
@@ -221,6 +228,9 @@ Route::group([
|
||||
Route::post('/services/{uuid}/storages', [ServicesController::class, 'create_storage'])->middleware(['api.ability:write']);
|
||||
Route::patch('/services/{uuid}/storages', [ServicesController::class, 'update_storage'])->middleware(['api.ability:write']);
|
||||
Route::delete('/services/{uuid}/storages/{storage_uuid}', [ServicesController::class, 'delete_storage'])->middleware(['api.ability:write']);
|
||||
Route::put('/services/{uuid}/storages/{storage_uuid}/backups', [VolumeBackupsController::class, 'upsert'])
|
||||
->defaults('resource_type', 'service')
|
||||
->middleware(['api.ability:write']);
|
||||
|
||||
Route::get('/services/{uuid}/envs', [ServicesController::class, 'envs'])->middleware(['api.ability:read']);
|
||||
Route::post('/services/{uuid}/envs', [ServicesController::class, 'create_env'])->middleware(['api.ability:write']);
|
||||
|
||||
+14
-1
@@ -229,6 +229,10 @@ Route::middleware(['auth', 'verified'])->group(function () {
|
||||
Route::get('/persistent-storage', ApplicationConfiguration::class)->name('project.application.persistent-storage');
|
||||
Route::get('/backups', ApplicationBackupIndex::class)->name('project.application.backup.index');
|
||||
Route::get('/backups/{backup_uuid}', ApplicationBackupShow::class)->name('project.application.backup.show');
|
||||
Route::get('/backups/{backup_uuid}/s3', ApplicationBackupShow::class)->name('project.application.backup.s3');
|
||||
Route::get('/backups/{backup_uuid}/retention', ApplicationBackupShow::class)->name('project.application.backup.retention');
|
||||
Route::get('/backups/{backup_uuid}/executions', ApplicationBackupShow::class)->name('project.application.backup.executions');
|
||||
Route::get('/backups/{backup_uuid}/danger', ApplicationBackupShow::class)->name('project.application.backup.danger');
|
||||
Route::get('/source', ApplicationConfiguration::class)->name('project.application.source');
|
||||
Route::get('/servers', ApplicationConfiguration::class)->name('project.application.servers');
|
||||
Route::get('/scheduled-tasks', ApplicationConfiguration::class)->name('project.application.scheduled-tasks.show');
|
||||
@@ -266,6 +270,10 @@ Route::middleware(['auth', 'verified'])->group(function () {
|
||||
Route::get('/terminal', ExecuteContainerCommand::class)->name('project.database.command')->middleware('can.access.terminal');
|
||||
Route::get('/backups', DatabaseBackupIndex::class)->name('project.database.backup.index');
|
||||
Route::get('/backups/{backup_uuid}', DatabaseBackupExecution::class)->name('project.database.backup.execution');
|
||||
Route::get('/backups/{backup_uuid}/s3', DatabaseBackupExecution::class)->name('project.database.backup.s3');
|
||||
Route::get('/backups/{backup_uuid}/retention', DatabaseBackupExecution::class)->name('project.database.backup.retention');
|
||||
Route::get('/backups/{backup_uuid}/executions', DatabaseBackupExecution::class)->name('project.database.backup.executions');
|
||||
Route::get('/backups/{backup_uuid}/danger', DatabaseBackupExecution::class)->name('project.database.backup.danger');
|
||||
});
|
||||
Route::prefix('project/{project_uuid}/environment/{environment_uuid}/service/{service_uuid}')->group(function () {
|
||||
Route::get('/', ServiceConfiguration::class)->name('project.service.configuration');
|
||||
@@ -279,6 +287,11 @@ Route::middleware(['auth', 'verified'])->group(function () {
|
||||
Route::get('/danger', ServiceConfiguration::class)->name('project.service.danger');
|
||||
Route::get('/terminal', ExecuteContainerCommand::class)->name('project.service.command')->middleware('can.access.terminal');
|
||||
Route::get('/{stack_service_uuid}/backups', ServiceDatabaseBackups::class)->name('project.service.database.backups');
|
||||
Route::get('/{stack_service_uuid}/backups/{backup_uuid}', ServiceDatabaseBackups::class)->name('project.service.database.backup.show');
|
||||
Route::get('/{stack_service_uuid}/backups/{backup_uuid}/s3', ServiceDatabaseBackups::class)->name('project.service.database.backup.s3');
|
||||
Route::get('/{stack_service_uuid}/backups/{backup_uuid}/retention', ServiceDatabaseBackups::class)->name('project.service.database.backup.retention');
|
||||
Route::get('/{stack_service_uuid}/backups/{backup_uuid}/executions', ServiceDatabaseBackups::class)->name('project.service.database.backup.executions');
|
||||
Route::get('/{stack_service_uuid}/backups/{backup_uuid}/danger', ServiceDatabaseBackups::class)->name('project.service.database.backup.danger');
|
||||
Route::get('/{stack_service_uuid}/import', ServiceIndex::class)->name('project.service.database.import')->middleware('can.update.resource');
|
||||
Route::get('/{stack_service_uuid}/advanced', ServiceIndex::class)->name('project.service.index.advanced');
|
||||
Route::get('/{stack_service_uuid}', ServiceIndex::class)->name('project.service.index');
|
||||
@@ -428,7 +441,7 @@ Route::middleware(['auth'])->group(function () {
|
||||
}
|
||||
|
||||
$execution = ScheduledVolumeBackupExecution::query()
|
||||
->with('scheduledVolumeBackup.volume.resource')
|
||||
->with('scheduledVolumeBackup.backupable.resource')
|
||||
->findOrFail(request()->route('executionId'));
|
||||
if ($team->id !== 0 && $team->id !== $execution->scheduledVolumeBackup->team_id) {
|
||||
return response()->json(['message' => 'Permission denied.'], 403);
|
||||
|
||||
Reference in new issue
Block a user