Skip to content

Commit 6b9e1f5

Browse files
committed
[pgmoneta#1089] fix the integration testing
Signed-off-by: Amr-Shams <amr.shams2015.as@gmail.com>
1 parent 8d78bc0 commit 6b9e1f5

12 files changed

Lines changed: 144 additions & 86 deletions

File tree

.github/workflows/ci.yml

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -167,13 +167,13 @@ jobs:
167167
path: /tmp/pgmoneta-test/log
168168
retention-days: 90
169169

170-
# storage:
171-
# needs: [format-check, build-linux]
172-
# strategy:
173-
# matrix:
174-
# platform: [ubuntu-latest]
175-
# pg_version: ["14"]
176-
# uses: ./.github/workflows/storage.yml
177-
# with:
178-
# platform: ${{ matrix.platform }}
179-
# pg_version: ${{ matrix.pg_version }}
170+
storage:
171+
needs: [format-check, build-linux]
172+
strategy:
173+
matrix:
174+
platform: [ubuntu-latest]
175+
pg_version: ["17"]
176+
uses: ./.github/workflows/storage.yml
177+
with:
178+
platform: ${{ matrix.platform }}
179+
pg_version: ${{ matrix.pg_version }}

.github/workflows/storage.yml

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ on:
66
pg_version:
77
description: PostgreSQL version to test
88
required: true
9-
default: "14"
9+
default: "17"
1010
type: string
1111
platform:
1212
description: GitHub runner platform
@@ -18,7 +18,7 @@ on:
1818
pg_version:
1919
description: PostgreSQL version to test
2020
required: true
21-
default: "14"
21+
default: "17"
2222
type: string
2323
platform:
2424
description: GitHub runner platform
@@ -366,35 +366,51 @@ jobs:
366366
367367
- name: Test S3 restore
368368
run: |
369+
set -euo pipefail
370+
369371
CLI="./build/src/pgmoneta-cli -c ${{ env.BASE_DIR }}/conf/pgmoneta_cli.conf"
370372
LABEL="${{ steps.backup.outputs.backup_label }}"
371-
UPLOAD_COUNT="${{ steps.list.outputs.upload_count }}"
373+
RESTORE_ROOT="${{ env.BASE_DIR }}/restore/$LABEL"
374+
375+
echo "start restore test $LABEL"
372376
373-
if ! $CLI s3 restore primary "$LABEL"; then
374-
echo "FAIL: restore command returned error"
377+
if ! $CLI s3 restore primary "$LABEL" "$RESTORE_ROOT"; then
378+
echo "fail: restore cmd error"
375379
cat ${{ env.LOG_DIR }}/pgmoneta.log
376380
exit 1
377381
fi
378-
sleep 10
379382
380-
RESTORE_DIR="${{ env.BASE_DIR }}/backup/primary/backup/$LABEL"
383+
sleep 5
384+
385+
RESTORE_DIR="$RESTORE_ROOT/primary-$LABEL"
381386
382-
if [ ! -d "$RESTORE_DIR/data" ]; then
383-
echo "FAIL: restored data directory not found at $RESTORE_DIR/data"
387+
if [ ! -d "$RESTORE_DIR" ]; then
388+
echo "fail: restore dir missing $RESTORE_DIR"
384389
cat ${{ env.LOG_DIR }}/pgmoneta.log
385390
exit 1
386391
fi
387392
388-
RESTORED_COUNT=$(find "$RESTORE_DIR" -type f | wc -l)
393+
test -f "$RESTORE_DIR/PG_VERSION" || { echo "fail: no PG_VERSION"; exit 1; }
394+
test -d "$RESTORE_DIR/base" || { echo "fail: no base/"; exit 1; }
395+
test -d "$RESTORE_DIR/global" || { echo "fail: no global/"; exit 1; }
389396
390-
if [ "$RESTORED_COUNT" -ne "$UPLOAD_COUNT" ]; then
391-
echo "FAIL: file count mismatch (uploaded: $UPLOAD_COUNT, restored: $RESTORED_COUNT)"
392-
echo "Restored files:"
393-
find "$RESTORE_DIR" -type f
397+
echo "structure ok"
398+
399+
FILES=$(find "$RESTORE_DIR" -type f | wc -l)
400+
401+
if [ "$FILES" -eq 0 ]; then
402+
echo "fail: empty restore"
394403
exit 1
395404
fi
396405
397-
echo "Restored files: $RESTORED_COUNT (matches upload count: $UPLOAD_COUNT)"
406+
echo "files restored: $FILES"
407+
if [ "$FILES" -lt $((UPLOAD_COUNT - 3)) ]; then
408+
echo "FAIL: file count mismatch (uploaded: $UPLOAD_COUNT, restored: $FILES)"
409+
echo "Restored files:"
410+
find "$RESTORE_DIR" -type f
411+
exit 1
412+
413+
echo "restore test ok"
398414
399415
- name: Test S3 delete
400416
run: |

doc/CLI.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -155,27 +155,26 @@ pgmoneta-cli restore primary newest timeline=2 /tmp
155155

156156
## s3 restore
157157

158-
Download a backup from S3 to the local backup directory
158+
Restore a backup directly from S3 to a target directory.
159159

160-
This subcommand downloads a backup from S3 storage and makes it available locally. The flow is:
160+
This subcommand stages a backup from S3 locally and then runs the normal restore workflow. The flow is:
161161

162162
* Download `backup.sha512`, `backup.info`, and `backup.manifest` from S3
163163
* Verify `backup.info` integrity using the SHA512 checksum
164164
* Download all data files listed in the manifest, applying the correct compression and encryption extensions
165-
* Atomically move the downloaded backup into the local backup directory
166-
167-
After `s3 restore` completes, the backup appears in `status details` and can be restored using `pgmoneta-cli restore`.
165+
* Restore the staged backup into the requested target directory using the standard restore workflow
166+
* Remove the staged local copy after a successful restore
168167

169168
Command
170169

171170
```sh
172-
pgmoneta-cli s3 restore <server> <timestamp>
171+
pgmoneta-cli s3 restore <server> <timestamp> [[current|name=X|xid=X|lsn=X|time=X|inclusive=X|timeline=X|action=X|primary|replica],*] <directory>
173172
```
174173

175174
Example
176175

177176
```sh
178-
pgmoneta-cli s3 restore primary 20260316000957
177+
pgmoneta-cli s3 restore primary 20260316000957 /tmp
179178
```
180179

181180
## verify
@@ -549,16 +548,17 @@ pgmoneta-cli s3 delete primary wal/
549548

550549
### s3 restore
551550

552-
Download a backup from S3 to the local backup directory.
551+
Restore a backup directly from S3 into a target directory.
553552

554553
- Downloads and verifies `backup.info` integrity via SHA512
555554
- Downloads all data files with correct compression/encryption extensions
556-
- The backup becomes available for `pgmoneta-cli restore`
555+
- Restores the staged backup into the requested directory
556+
- Cleans up the staged local copy after success
557557

558558
Examples
559559

560560
```sh
561-
pgmoneta-cli s3 restore primary 20260316000957
561+
pgmoneta-cli s3 restore primary 20260316000957 /tmp
562562
```
563563
## clear
564564

doc/S3.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,14 @@ pgmoneta-cli s3 delete primary <prefix>
139139

140140
`pgmoneta-cli s3 delete` removes all objects under `<s3_base_dir>/<server>/backup/<prefix>`.
141141

142+
Restore a backup from S3:
143+
144+
```sh
145+
pgmoneta-cli s3 restore primary <label> [position] <directory>
146+
```
147+
148+
`pgmoneta-cli s3 restore` downloads the backup metadata and data files from S3, stages them locally, and then restores the backup into the requested target directory using the normal restore workflow.
149+
142150
## Per-Server Configuration
143151

144152
All S3 configuration settings can be specified within a server's configuration section. This allows you to use different S3 buckets, credentials, or even regions for different PostgreSQL servers.

doc/manual/en/05-cli.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -173,25 +173,24 @@ pgmoneta-cli restore primary newest timeline=2 /tmp
173173
174174
Download a backup from S3 to the local backup directory
175175
176-
This subcommand downloads a backup from S3 storage and makes it available locally. The flow is:
176+
This subcommand stages a backup from S3 locally and then runs the normal restore workflow. The flow is:
177177
178178
* Download `backup.sha512`, `backup.info`, and `backup.manifest` from S3
179179
* Verify `backup.info` integrity using the SHA512 checksum
180180
* Download all data files listed in the manifest, applying the correct compression and encryption extensions
181-
* Atomically move the downloaded backup into the local backup directory
182-
183-
After `s3 restore` completes, the backup appears in `status details` and can be restored using `pgmoneta-cli restore`.
181+
* Restore the staged backup into the requested target directory using the standard restore workflow
182+
* Remove the staged local copy after a successful restore
184183
185184
Command
186185
187186
``` sh
188-
pgmoneta-cli s3 restore <server> <timestamp>
187+
pgmoneta-cli s3 restore <server> <timestamp> [[current|name=X|xid=X|lsn=X|time=X|inclusive=X|timeline=X|action=X|primary|replica],*] <directory>
189188
```
190189
191190
Example
192191
193192
``` sh
194-
pgmoneta-cli s3 restore primary 20260316000957
193+
pgmoneta-cli s3 restore primary 20260316000957 /tmp
195194
```
196195
197196
## verify
@@ -587,16 +586,17 @@ pgmoneta-cli s3 delete primary wal/
587586
588587
### s3 restore
589588
590-
Download a backup from S3 to the local backup directory.
589+
Restore a backup directly from S3 into a target directory.
591590
592591
- Downloads and verifies `backup.info` integrity via SHA512
593592
- Downloads all data files with correct compression/encryption extensions
594-
- The backup becomes available for `pgmoneta-cli restore`
593+
- Restores the staged backup into the requested directory
594+
- Cleans up the staged local copy after success
595595
596596
Examples
597597
598598
``` sh
599-
pgmoneta-cli s3 restore primary 20260316000957
599+
pgmoneta-cli s3 restore primary 20260316000957 /tmp
600600
```
601601
602602
## clear

doc/manual/en/09-restore.md

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -96,18 +96,15 @@ This command take the latest backup and all Write-Ahead Log (WAL) segments and r
9696

9797
## Restore from S3
9898

99-
If your backups are stored in S3, you first need to download them to the local backup directory using `pgmoneta-cli s3 restore`, then restore normally.
99+
If your backups are stored in S3, you can restore them directly using `pgmoneta-cli s3 restore`.
100100

101-
Step 1: Download the backup from S3
101+
Example:
102102

103103
```
104-
pgmoneta-cli s3 restore primary 20260316000957
104+
pgmoneta-cli s3 restore primary 20260316000957 /tmp
105105
```
106106

107-
This downloads the backup files from S3, verifies `backup.info` integrity via SHA512, and places the backup in the local backup directory.
108-
109-
Step 2: Restore the backup
110-
107+
This stages the backup files from S3, verifies `backup.info` integrity via SHA512, restores the backup into the requested target directory, and removes the staged local copy after success.
111108
```
112109
pgmoneta-cli restore primary 20260316000957 current /tmp
113110
```

doc/manual/en/17-s3.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,9 @@ pgmoneta-cli s3 delete primary <prefix>
103103
Restore a backup from S3:
104104

105105
``` sh
106-
pgmoneta-cli s3 restore primary <label>
106+
pgmoneta-cli s3 restore primary <label> [position] <directory>
107107
```
108108

109-
`pgmoneta-cli s3 restore` downloads all files from S3 for the given backup label into the local backup directory.
109+
`pgmoneta-cli s3 restore` downloads all files from S3 for the given backup label, stages them locally, and restores the backup into the requested target directory using the standard restore workflow.
110110

111-
Metadata files (`backup.info`, `backup.sha512`, `backup.manifest`) are downloaded as temporary files first, then renamed in order after all data files are restored. `backup.info` is renamed last and its presence marks a complete restore.
111+
Metadata files (`backup.info`, `backup.sha512`, `backup.manifest`) are downloaded as temporary files first. `backup.info` is verified before file download starts, then renamed into place so the staged backup metadata matches the downloaded objects before the restore workflow runs.

src/cli.c

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ static int backup(SSL* ssl, int socket, char* server, uint8_t compression, uint8
122122
static int list_backup(SSL* ssl, int socket, char* server, char* sort_order, uint8_t compression, uint8_t encryption, int32_t output_format);
123123
static int list_s3_objects(SSL* ssl, int socket, char* server, char* prefix, uint8_t compression, uint8_t encryption, int32_t output_format);
124124
static int delete_s3_objects(SSL* ssl, int socket, char* server, char* prefix, uint8_t compression, uint8_t encryption, int32_t output_format);
125-
static int restore_s3_objects(SSL* ssl, int socket, char* server, char* prefix, uint8_t compression, uint8_t encryption, int32_t output_format);
125+
static int restore_s3_objects(SSL* ssl, int socket, char* server, char* prefix, char* position, char* directory, uint8_t compression, uint8_t encryption, int32_t output_format);
126126
static int restore(SSL* ssl, int socket, char* server, char* backup_id, char* position, char* directory, uint8_t compression, uint8_t encryption, int32_t output_format);
127127
static int verify(SSL* ssl, int socket, char* server, char* backup_id, char* directory, char* files, uint8_t compression, uint8_t encryption, int32_t output_format);
128128
static int archive(SSL* ssl, int socket, char* server, char* backup_id, char* position, char* directory, uint8_t compression, uint8_t encryption, int32_t output_format);
@@ -277,7 +277,7 @@ struct pgmoneta_command command_table[] = {
277277
.log_message = "<s3 delete>"},
278278
{.command = "s3",
279279
.subcommand = "restore",
280-
.accepted_argument_count = {1, 2},
280+
.accepted_argument_count = {3, 4},
281281
.action = MANAGEMENT_S3_RESTORE,
282282
.deprecated = false,
283283
.log_message = "<s3 restore>"},
@@ -938,7 +938,14 @@ main(int argc, char** argv)
938938
}
939939
else if (parsed.cmd->action == MANAGEMENT_S3_RESTORE)
940940
{
941-
exit_code = restore_s3_objects(s_ssl, socket, parsed.args[0], parsed.args[1], compression, encryption, output_format);
941+
if (parsed.args[3])
942+
{
943+
exit_code = restore_s3_objects(s_ssl, socket, parsed.args[0], parsed.args[1], parsed.args[2], parsed.args[3], compression, encryption, output_format);
944+
}
945+
else
946+
{
947+
exit_code = restore_s3_objects(s_ssl, socket, parsed.args[0], parsed.args[1], NULL, parsed.args[2], compression, encryption, output_format);
948+
}
942949
}
943950
else if (parsed.cmd->action == MANAGEMENT_RESTORE)
944951
{
@@ -1148,7 +1155,7 @@ help_s3(void)
11481155
printf("Manage the s3\n");
11491156
printf(" pgmoneta-cli s3 ls <server>\n");
11501157
printf(" pgmoneta-cli s3 delete <server> <prefix>\n");
1151-
printf(" pgmoneta-cli s3 restore <server> <prefix> \n");
1158+
printf(" pgmoneta-cli s3 restore <server> <prefix> [[current|name=X|xid=X|lsn=X|time=X|inclusive=X|timeline=X|action=X|primary|replica],*] <directory>\n");
11521159
}
11531160

11541161
static void
@@ -1458,9 +1465,9 @@ delete_s3_objects(SSL* ssl, int socket, char* server, char* prefix, uint8_t comp
14581465
return 1;
14591466
}
14601467
static int
1461-
restore_s3_objects(SSL* ssl, int socket, char* server, char* prefix, uint8_t compression, uint8_t encryption, int32_t output_format)
1468+
restore_s3_objects(SSL* ssl, int socket, char* server, char* prefix, char* position, char* directory, uint8_t compression, uint8_t encryption, int32_t output_format)
14621469
{
1463-
if (pgmoneta_management_request_restore_s3_objects(ssl, socket, server, prefix, compression, encryption, output_format))
1470+
if (pgmoneta_management_request_restore_s3_objects(ssl, socket, server, prefix, position, directory, compression, encryption, output_format))
14641471
{
14651472
goto error;
14661473
}

src/include/management.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -517,14 +517,16 @@ pgmoneta_management_request_delete_s3_objects(SSL* ssl, int socket, char* server
517517
* @param ssl The SSL connection
518518
* @param socket The socket descriptor
519519
* @param server The server
520-
* @param prefix The prefix to delete under the server backup path
520+
* @param prefix The prefix to restore under the server backup path
521+
* @param position The recovery target parameters
522+
* @param directory The restore target directory
521523
* @param compression The compress method for wire protocol
522524
* @param encryption The encrypt method for wire protocol
523525
* @param output_format The output format
524526
* @return 0 upon success, otherwise 1
525527
*/
526528
int
527-
pgmoneta_management_request_restore_s3_objects(SSL* ssl, int socket, char* server, char* prefix, uint8_t compression, uint8_t encryption, int32_t output_format);
529+
pgmoneta_management_request_restore_s3_objects(SSL* ssl, int socket, char* server, char* prefix, char* position, char* directory, uint8_t compression, uint8_t encryption, int32_t output_format);
528530

529531
/**
530532
* Create a restore request

src/libpgmoneta/management.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ pgmoneta_management_request_delete_s3_objects(SSL* ssl, int socket, char* server
198198
}
199199

200200
int
201-
pgmoneta_management_request_restore_s3_objects(SSL* ssl, int socket, char* server, char* prefix, uint8_t compression, uint8_t encryption, int32_t output_format)
201+
pgmoneta_management_request_restore_s3_objects(SSL* ssl, int socket, char* server, char* prefix, char* position, char* directory, uint8_t compression, uint8_t encryption, int32_t output_format)
202202
{
203203
struct json* j = NULL;
204204
struct json* request = NULL;
@@ -215,6 +215,8 @@ pgmoneta_management_request_restore_s3_objects(SSL* ssl, int socket, char* serve
215215

216216
pgmoneta_json_put(request, MANAGEMENT_ARGUMENT_SERVER, (uintptr_t)server, ValueString);
217217
pgmoneta_json_put(request, MANAGEMENT_ARGUMENT_S3_PREFIX, (uintptr_t)prefix, ValueString);
218+
pgmoneta_json_put(request, MANAGEMENT_ARGUMENT_POSITION, (uintptr_t)position, ValueString);
219+
pgmoneta_json_put(request, MANAGEMENT_ARGUMENT_DIRECTORY, (uintptr_t)directory, ValueString);
218220

219221
if (pgmoneta_management_write_json(ssl, socket, compression, encryption, j))
220222
{

0 commit comments

Comments
 (0)