mirror of
https://github.com/tiennm99/coolify.git
synced 2026-04-17 17:21:04 +00:00
feat: add S3 storage integration for file import
This commit introduces functionality for integrating S3 storage into the import process. It allows users to select S3 storage, check for file existence, and download files directly from S3. This enhancement improves the flexibility of the import feature by enabling users to work with files stored in S3, addressing a common use case for teams that utilize cloud storage solutions.
This commit is contained in:
@@ -68,22 +68,21 @@
|
||||
</span>
|
||||
</div>
|
||||
<div class="text-gray-600 dark:text-gray-400 text-sm">
|
||||
Started: {{ formatDateInServerTimezone(data_get($execution, 'created_at'), $this->server()) }}
|
||||
@if (data_get($execution, 'status') !== 'running')
|
||||
<br>Ended:
|
||||
{{ formatDateInServerTimezone(data_get($execution, 'finished_at'), $this->server()) }}
|
||||
<br>Duration:
|
||||
{{ calculateDuration(data_get($execution, 'created_at'), data_get($execution, 'finished_at')) }}
|
||||
<br>Finished {{ \Carbon\Carbon::parse(data_get($execution, 'finished_at'))->diffForHumans() }}
|
||||
@if (data_get($execution, 'status') === 'running')
|
||||
<span title="Started: {{ formatDateInServerTimezone(data_get($execution, 'created_at'), $this->server()) }}">
|
||||
Running for {{ calculateDuration(data_get($execution, 'created_at'), now()) }}
|
||||
</span>
|
||||
@else
|
||||
<span title="Started: {{ formatDateInServerTimezone(data_get($execution, 'created_at'), $this->server()) }} Ended: {{ formatDateInServerTimezone(data_get($execution, 'finished_at'), $this->server()) }}">
|
||||
{{ \Carbon\Carbon::parse(data_get($execution, 'finished_at'))->diffForHumans() }}
|
||||
({{ calculateDuration(data_get($execution, 'created_at'), data_get($execution, 'finished_at')) }})
|
||||
• {{ \Carbon\Carbon::parse(data_get($execution, 'finished_at'))->format('M j, H:i') }}
|
||||
</span>
|
||||
@endif
|
||||
• Database: {{ data_get($execution, 'database_name', 'N/A') }}
|
||||
@if(data_get($execution, 'size'))
|
||||
• Size: {{ formatBytes(data_get($execution, 'size')) }}
|
||||
@endif
|
||||
</div>
|
||||
<div class="text-gray-600 dark:text-gray-400 text-sm">
|
||||
Database: {{ data_get($execution, 'database_name', 'N/A') }}
|
||||
</div>
|
||||
<div class="text-gray-600 dark:text-gray-400 text-sm">
|
||||
Size: {{ data_get($execution, 'size') }} B /
|
||||
{{ round((int) data_get($execution, 'size') / 1024, 2) }} kB /
|
||||
{{ round((int) data_get($execution, 'size') / 1024 / 1024, 3) }} MB
|
||||
</div>
|
||||
<div class="text-gray-600 dark:text-gray-400 text-sm">
|
||||
Location: {{ data_get($execution, 'filename', 'N/A') }}
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
<div x-data="{ error: $wire.entangle('error'), filesize: $wire.entangle('filesize'), filename: $wire.entangle('filename'), isUploading: $wire.entangle('isUploading'), progress: $wire.entangle('progress') }">
|
||||
<div x-data="{
|
||||
error: $wire.entangle('error'),
|
||||
filesize: $wire.entangle('filesize'),
|
||||
filename: $wire.entangle('filename'),
|
||||
isUploading: $wire.entangle('isUploading'),
|
||||
progress: $wire.entangle('progress'),
|
||||
s3DownloadInProgress: $wire.entangle('s3DownloadInProgress'),
|
||||
s3DownloadedFile: $wire.entangle('s3DownloadedFile'),
|
||||
s3FileSize: $wire.entangle('s3FileSize')
|
||||
}">
|
||||
<script type="text/javascript" src="{{ URL::asset('js/dropzone.js') }}"></script>
|
||||
@script
|
||||
<script data-navigate-once>
|
||||
@@ -103,7 +112,65 @@
|
||||
<div x-show="isUploading">
|
||||
<progress max="100" x-bind:value="progress" class="progress progress-warning"></progress>
|
||||
</div>
|
||||
<h3 class="pt-6" x-show="filename && !error">File Information</h3>
|
||||
|
||||
@if ($availableS3Storages->count() > 0)
|
||||
<div class="pt-2 text-center text-xl font-bold">
|
||||
Or
|
||||
</div>
|
||||
<h3 class="pt-4">Restore from S3</h3>
|
||||
<div class="flex flex-col gap-2">
|
||||
<x-forms.select label="S3 Storage" wire:model="s3StorageId">
|
||||
<option value="">Select S3 Storage</option>
|
||||
@foreach ($availableS3Storages as $storage)
|
||||
<option value="{{ $storage->id }}">{{ $storage->name }}
|
||||
@if ($storage->description)
|
||||
- {{ $storage->description }}
|
||||
@endif
|
||||
</option>
|
||||
@endforeach
|
||||
</x-forms.select>
|
||||
|
||||
<x-forms.input label="S3 File Path (within bucket)"
|
||||
helper="Path to the backup file in your S3 bucket, e.g., /backups/database-2025-01-15.gz"
|
||||
placeholder="/backups/database-backup.gz" wire:model='s3Path'></x-forms.input>
|
||||
|
||||
<div class="flex gap-2">
|
||||
<x-forms.button class="w-full" wire:click='checkS3File'
|
||||
:disabled="!$s3StorageId || !$s3Path">
|
||||
Check File
|
||||
</x-forms.button>
|
||||
</div>
|
||||
|
||||
<div x-show="s3FileSize && !s3DownloadedFile" class="pt-2">
|
||||
<div class="text-sm">File found in S3 ({{ formatBytes($s3FileSize ?? 0) }})</div>
|
||||
<div class="flex gap-2 pt-2">
|
||||
<x-forms.button class="w-full" wire:click='downloadFromS3'>
|
||||
Download & Prepare for Restore
|
||||
</x-forms.button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div x-show="s3DownloadInProgress" class="pt-2">
|
||||
<div class="text-sm text-warning">Downloading from S3... This may take a few minutes for large
|
||||
backups.</div>
|
||||
<livewire:activity-monitor header="S3 Download Progress" :showWaiting="false" />
|
||||
</div>
|
||||
|
||||
<div x-show="s3DownloadedFile && !s3DownloadInProgress" class="pt-2">
|
||||
<div class="text-sm text-success">File downloaded successfully and ready for restore.</div>
|
||||
<div class="flex gap-2 pt-2">
|
||||
<x-forms.button class="w-full" wire:click='restoreFromS3'>
|
||||
Restore Database from S3
|
||||
</x-forms.button>
|
||||
<x-forms.button class="w-full" wire:click='cancelS3Download'>
|
||||
Cancel
|
||||
</x-forms.button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<h3 class="pt-6" x-show="filename && !error && !s3DownloadedFile">File Information</h3>
|
||||
<div x-show="filename && !error">
|
||||
<div>Location: <span x-text="filename ?? 'N/A'"></span> <span x-text="filesize">/ </span></div>
|
||||
<x-forms.button class="w-full my-4" wire:click='runImport'>Restore Backup</x-forms.button>
|
||||
|
||||
@@ -70,32 +70,32 @@
|
||||
</div>
|
||||
<div class="text-gray-600 dark:text-gray-400 text-sm">
|
||||
@if ($backup->latest_log)
|
||||
Started:
|
||||
{{ formatDateInServerTimezone(data_get($backup->latest_log, 'created_at'), $backup->server()) }}
|
||||
@if (data_get($backup->latest_log, 'status') !== 'running')
|
||||
<br>Ended:
|
||||
{{ formatDateInServerTimezone(data_get($backup->latest_log, 'finished_at'), $backup->server()) }}
|
||||
<br>Duration:
|
||||
{{ calculateDuration(data_get($backup->latest_log, 'created_at'), data_get($backup->latest_log, 'finished_at')) }}
|
||||
<br>Finished
|
||||
{{ \Carbon\Carbon::parse(data_get($backup->latest_log, 'finished_at'))->diffForHumans() }}
|
||||
@endif
|
||||
@if ($backup->save_s3)
|
||||
<br>S3 Storage: Enabled
|
||||
@if (data_get($backup->latest_log, 'status') === 'running')
|
||||
<span title="Started: {{ formatDateInServerTimezone(data_get($backup->latest_log, 'created_at'), $backup->server()) }}">
|
||||
Running for {{ calculateDuration(data_get($backup->latest_log, 'created_at'), now()) }}
|
||||
</span>
|
||||
@else
|
||||
<span title="Started: {{ formatDateInServerTimezone(data_get($backup->latest_log, 'created_at'), $backup->server()) }} Ended: {{ formatDateInServerTimezone(data_get($backup->latest_log, 'finished_at'), $backup->server()) }}">
|
||||
{{ \Carbon\Carbon::parse(data_get($backup->latest_log, 'finished_at'))->diffForHumans() }}
|
||||
({{ calculateDuration(data_get($backup->latest_log, 'created_at'), data_get($backup->latest_log, 'finished_at')) }})
|
||||
• {{ \Carbon\Carbon::parse(data_get($backup->latest_log, 'finished_at'))->format('M j, H:i') }}
|
||||
</span>
|
||||
@endif
|
||||
@if (data_get($backup->latest_log, 'status') === 'success')
|
||||
@php
|
||||
$size = data_get($backup->latest_log, 'size', 0);
|
||||
$sizeFormatted =
|
||||
$size > 0 ? number_format($size / 1024 / 1024, 2) . ' MB' : 'Unknown';
|
||||
@endphp
|
||||
<br>Last Backup Size: {{ $sizeFormatted }}
|
||||
@if ($size > 0)
|
||||
• Size: {{ formatBytes($size) }}
|
||||
@endif
|
||||
@endif
|
||||
@if ($backup->save_s3)
|
||||
• S3: Enabled
|
||||
@endif
|
||||
@else
|
||||
Last Run: Never
|
||||
<br>Total Executions: 0
|
||||
Last Run: Never • Total Executions: 0
|
||||
@if ($backup->save_s3)
|
||||
<br>S3 Storage: Enabled
|
||||
• S3: Enabled
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
@@ -154,27 +154,36 @@
|
||||
</div>
|
||||
<div class="text-gray-600 dark:text-gray-400 text-sm">
|
||||
@if ($backup->latest_log)
|
||||
Started:
|
||||
{{ formatDateInServerTimezone(data_get($backup->latest_log, 'created_at'), $backup->server()) }}
|
||||
@if (data_get($backup->latest_log, 'status') !== 'running')
|
||||
<br>Ended:
|
||||
{{ formatDateInServerTimezone(data_get($backup->latest_log, 'finished_at'), $backup->server()) }}
|
||||
<br>Duration:
|
||||
{{ calculateDuration(data_get($backup->latest_log, 'created_at'), data_get($backup->latest_log, 'finished_at')) }}
|
||||
<br>Finished
|
||||
{{ \Carbon\Carbon::parse(data_get($backup->latest_log, 'finished_at'))->diffForHumans() }}
|
||||
@if (data_get($backup->latest_log, 'status') === 'running')
|
||||
<span title="Started: {{ formatDateInServerTimezone(data_get($backup->latest_log, 'created_at'), $backup->server()) }}">
|
||||
Running for {{ calculateDuration(data_get($backup->latest_log, 'created_at'), now()) }}
|
||||
</span>
|
||||
@else
|
||||
<span title="Started: {{ formatDateInServerTimezone(data_get($backup->latest_log, 'created_at'), $backup->server()) }} Ended: {{ formatDateInServerTimezone(data_get($backup->latest_log, 'finished_at'), $backup->server()) }}">
|
||||
{{ \Carbon\Carbon::parse(data_get($backup->latest_log, 'finished_at'))->diffForHumans() }}
|
||||
({{ calculateDuration(data_get($backup->latest_log, 'created_at'), data_get($backup->latest_log, 'finished_at')) }})
|
||||
• {{ \Carbon\Carbon::parse(data_get($backup->latest_log, 'finished_at'))->format('M j, H:i') }}
|
||||
</span>
|
||||
@endif
|
||||
@if (data_get($backup->latest_log, 'status') === 'success')
|
||||
@php
|
||||
$size = data_get($backup->latest_log, 'size', 0);
|
||||
@endphp
|
||||
@if ($size > 0)
|
||||
• Size: {{ formatBytes($size) }}
|
||||
@endif
|
||||
@endif
|
||||
<br><br>Total Executions: {{ $backup->executions()->count() }}
|
||||
@if ($backup->save_s3)
|
||||
<br>S3 Storage: Enabled
|
||||
• S3: Enabled
|
||||
@endif
|
||||
<br>Total Executions: {{ $backup->executions()->count() }}
|
||||
@php
|
||||
$successCount = $backup->executions()->where('status', 'success')->count();
|
||||
$totalCount = $backup->executions()->count();
|
||||
$successRate = $totalCount > 0 ? round(($successCount / $totalCount) * 100) : 0;
|
||||
@endphp
|
||||
@if ($totalCount > 0)
|
||||
<br>Success Rate: <span @class([
|
||||
• Success Rate: <span @class([
|
||||
'font-medium',
|
||||
'text-green-600' => $successRate >= 80,
|
||||
'text-yellow-600' => $successRate >= 50 && $successRate < 80,
|
||||
@@ -182,19 +191,10 @@
|
||||
])>{{ $successRate }}%</span>
|
||||
({{ $successCount }}/{{ $totalCount }})
|
||||
@endif
|
||||
@if (data_get($backup->latest_log, 'status') === 'success')
|
||||
@php
|
||||
$size = data_get($backup->latest_log, 'size', 0);
|
||||
$sizeFormatted =
|
||||
$size > 0 ? number_format($size / 1024 / 1024, 2) . ' MB' : 'Unknown';
|
||||
@endphp
|
||||
<br>Last Backup Size: {{ $sizeFormatted }}
|
||||
@endif
|
||||
@else
|
||||
Last Run: Never
|
||||
<br>Total Executions: 0
|
||||
Last Run: Never • Total Executions: 0
|
||||
@if ($backup->save_s3)
|
||||
<br>S3 Storage: Enabled
|
||||
• S3: Enabled
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user