Skip to content

Commit 2dcc46e

Browse files
committed
backups: support Cloudflare R2 by listing uploaded parts from Wings
1 parent 0dc77ae commit 2dcc46e

File tree

2 files changed

+21
-6
lines changed

2 files changed

+21
-6
lines changed

app/Http/Controllers/Api/Remote/Backups/BackupStatusController.php

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public function index(ReportBackupCompleteRequest $request, string $backup)
6666
// being completed in S3 correctly.
6767
$adapter = $this->backupManager->adapter();
6868
if ($adapter instanceof AwsS3Adapter) {
69-
$this->completeMultipartUpload($model, $adapter, $successful);
69+
$this->completeMultipartUpload($model, $adapter, $successful, $request->input('parts'));
7070
}
7171
});
7272

@@ -85,7 +85,7 @@ public function index(ReportBackupCompleteRequest $request, string $backup)
8585
*
8686
* @throws \Throwable
8787
*/
88-
public function restore(Request $request, string $backup)
88+
public function restore(Request $request, string $backup): JsonResponse
8989
{
9090
/** @var \Pterodactyl\Models\Backup $model */
9191
$model = Backup::query()->where('uuid', $backup)->firstOrFail();
@@ -101,23 +101,24 @@ public function restore(Request $request, string $backup)
101101
}
102102

103103
/**
104-
* Marks a multipart upload in a given S3-compatiable instance as failed or successful for
104+
* Marks a multipart upload in a given S3-compatible instance as failed or successful for
105105
* the given backup.
106106
*
107107
* @throws \Exception
108108
* @throws \Pterodactyl\Exceptions\DisplayException
109109
*/
110-
protected function completeMultipartUpload(Backup $backup, AwsS3Adapter $adapter, bool $successful)
110+
protected function completeMultipartUpload(Backup $backup, AwsS3Adapter $adapter, bool $successful, ?array $parts): void
111111
{
112112
// This should never really happen, but if it does don't let us fall victim to Amazon's
113113
// wildly fun error messaging. Just stop the process right here.
114114
if (empty($backup->upload_id)) {
115-
// A failed backup doesn't need to error here, this can happen if the backup encouters
115+
// A failed backup doesn't need to error here, this can happen if the backup encounters
116116
// an error before we even start the upload. AWS gives you tooling to clear these failed
117117
// multipart uploads as needed too.
118118
if (!$successful) {
119119
return;
120120
}
121+
121122
throw new DisplayException('Cannot complete backup request: no upload_id present on model.');
122123
}
123124

@@ -136,9 +137,20 @@ protected function completeMultipartUpload(Backup $backup, AwsS3Adapter $adapter
136137

137138
// Otherwise send a CompleteMultipartUpload request.
138139
$params['MultipartUpload'] = [
139-
'Parts' => $client->execute($client->getCommand('ListParts', $params))['Parts'],
140+
'Parts' => [],
140141
];
141142

143+
if (is_null($parts)) {
144+
$params['MultipartUpload']['Parts'] = $client->execute($client->getCommand('ListParts', $params))['Parts'];
145+
} else {
146+
foreach ($parts as $part) {
147+
$params['MultipartUpload']['Parts'][] = [
148+
'ETag' => $part['etag'],
149+
'PartNumber' => $part['part_number'],
150+
];
151+
}
152+
}
153+
142154
$client->execute($client->getCommand('CompleteMultipartUpload', $params));
143155
}
144156
}

app/Http/Requests/Api/Remote/ReportBackupCompleteRequest.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ public function rules()
1616
'checksum' => 'nullable|string|required_if:successful,true',
1717
'checksum_type' => 'nullable|string|required_if:successful,true',
1818
'size' => 'nullable|numeric|required_if:successful,true',
19+
'parts' => 'nullable|array',
20+
'parts.*.etag' => 'required|string',
21+
'parts.*.part_number' => 'required|numeric',
1922
];
2023
}
2124
}

0 commit comments

Comments
 (0)