backups: support Cloudflare R2 by listing uploaded parts from Wings

This commit is contained in:
Matthew Penner 2022-09-26 11:15:52 -06:00
parent 0dc77aec25
commit 2dcc46ecd6
No known key found for this signature in database
GPG key ID: 31311906AD4CF6D6
2 changed files with 21 additions and 6 deletions

View file

@ -66,7 +66,7 @@ class BackupStatusController extends Controller
// being completed in S3 correctly.
$adapter = $this->backupManager->adapter();
if ($adapter instanceof AwsS3Adapter) {
$this->completeMultipartUpload($model, $adapter, $successful);
$this->completeMultipartUpload($model, $adapter, $successful, $request->input('parts'));
}
});
@ -85,7 +85,7 @@ class BackupStatusController extends Controller
*
* @throws \Throwable
*/
public function restore(Request $request, string $backup)
public function restore(Request $request, string $backup): JsonResponse
{
/** @var \Pterodactyl\Models\Backup $model */
$model = Backup::query()->where('uuid', $backup)->firstOrFail();
@ -101,23 +101,24 @@ class BackupStatusController extends Controller
}
/**
* Marks a multipart upload in a given S3-compatiable instance as failed or successful for
* Marks a multipart upload in a given S3-compatible instance as failed or successful for
* the given backup.
*
* @throws \Exception
* @throws \Pterodactyl\Exceptions\DisplayException
*/
protected function completeMultipartUpload(Backup $backup, AwsS3Adapter $adapter, bool $successful)
protected function completeMultipartUpload(Backup $backup, AwsS3Adapter $adapter, bool $successful, ?array $parts): void
{
// This should never really happen, but if it does don't let us fall victim to Amazon's
// wildly fun error messaging. Just stop the process right here.
if (empty($backup->upload_id)) {
// A failed backup doesn't need to error here, this can happen if the backup encouters
// A failed backup doesn't need to error here, this can happen if the backup encounters
// an error before we even start the upload. AWS gives you tooling to clear these failed
// multipart uploads as needed too.
if (!$successful) {
return;
}
throw new DisplayException('Cannot complete backup request: no upload_id present on model.');
}
@ -136,9 +137,20 @@ class BackupStatusController extends Controller
// Otherwise send a CompleteMultipartUpload request.
$params['MultipartUpload'] = [
'Parts' => $client->execute($client->getCommand('ListParts', $params))['Parts'],
'Parts' => [],
];
if (is_null($parts)) {
$params['MultipartUpload']['Parts'] = $client->execute($client->getCommand('ListParts', $params))['Parts'];
} else {
foreach ($parts as $part) {
$params['MultipartUpload']['Parts'][] = [
'ETag' => $part['etag'],
'PartNumber' => $part['part_number'],
];
}
}
$client->execute($client->getCommand('CompleteMultipartUpload', $params));
}
}

View file

@ -16,6 +16,9 @@ class ReportBackupCompleteRequest extends FormRequest
'checksum' => 'nullable|string|required_if:successful,true',
'checksum_type' => 'nullable|string|required_if:successful,true',
'size' => 'nullable|numeric|required_if:successful,true',
'parts' => 'nullable|array',
'parts.*.etag' => 'required|string',
'parts.*.part_number' => 'required|numeric',
];
}
}