Skip to content

Commit 2ee47a2

Browse files
authored
Merge pull request #8 from significa/ensure-no-volumes-left-improvements
Allow passing ensure-no-volumes-left from workflow and documentation improvements
2 parents 97cf065 + 8457584 commit 2ee47a2

File tree

3 files changed

+74
-60
lines changed

3 files changed

+74
-60
lines changed

.github/workflows/trigger-backup.yaml

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,34 @@ on:
44
workflow_call:
55
inputs:
66
fly-app:
7-
description: 'The Fly app name of your db backup worker.'
7+
description: The Fly app name of your db backup worker.
88
required: true
99
type: string
1010
volume-size:
11-
description: 'The volume size in GB for the volume of the backup worker.'
11+
description: The volume size in GB for the volume of the backup worker.
1212
required: false
1313
type: number
1414
machine-size:
15-
description: 'Fly machines v2 size (https://fly.io/docs/about/pricing/#machines)'
15+
description: Fly machines v2 size (https://fly.io/docs/about/pricing/#machines)
1616
required: false
1717
type: string
1818
region:
19-
description: 'The region to run the backup worker from.'
19+
description: The region to run the backup worker from.
2020
required: false
2121
type: string
2222
timeout:
23-
description: 'Backup GitHub action step timeout, in minutes.'
23+
description: Backup GitHub action step timeout, in minutes.
2424
required: false
2525
type: number
2626
docker-image:
27-
description: 'The image of the backup worker. Usefull to override with specific versions.'
27+
description: The image of the backup worker. Usefull to override with specific versions.
2828
required: false
2929
type: string
30+
ensure-no-volumes-left:
31+
description: >-
32+
Makes the action crash if when the backup finishes there are still volumes in the app
33+
required: false
34+
type: boolean
3035

3136
secrets:
3237
FLY_API_TOKEN:
@@ -55,3 +60,4 @@ jobs:
5560
FLY_MACHINE_SIZE: ${{ inputs.machine-size }}
5661
FLY_VOLUME_SIZE: ${{ inputs.volume-size }}
5762
DOCKER_IMAGE: ${{ inputs.docker-image }}
63+
ENSURE_NO_VOLUMES_LEFT: ${{ inputs.ensure-no-volumes-left }}

README.md

Lines changed: 49 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
This is ~~a hacky~~ an interesting way to have a Fly app that dumps postgres databases
44
that are also on Fly, to AWS S3 buckets.
5-
It uses a dedicated app for the *backup worker* that is _woken up_ to start the dump.
5+
It uses a dedicated app for the _backup worker_ that is _woken up_ to start the dump.
66
When it finishes it is _scaled_ back to 0, meaning **it is not billable when idle**,
7-
you only pay for the backup time (it is close to free, and supper affordable even with
7+
you only pay for the backup time (it is close to free, and supper affordable even with
88
high end machines). It leverages Fly machines to dynamically deploy volumes and servers on demand.
99

1010

@@ -25,6 +25,7 @@ Have a look into [create-resources-utils](./create-resources-utils) for scripts
2525
requirements in a simple way.
2626

2727
1. In a PG shell inside your Fly Postgres instance, create an user with read permissions:
28+
2829
```sql
2930
CREATE USER db_backup_worker WITH PASSWORD '<password>';
3031
GRANT CONNECT ON DATABASE <db_name> TO db_backup_worker;
@@ -43,22 +44,20 @@ requirements in a simple way.
4344
IAM policy:
4445
```json
4546
{
46-
"Version": "2012-10-17",
47-
"Statement": [
48-
{
49-
"Sid": "WriteDatabaseBackups",
50-
"Effect": "Allow",
51-
"Action": [
52-
"s3:PutObject",
53-
"s3:AbortMultipartUpload",
54-
"s3:ListMultipartUploadParts"
55-
],
56-
"Resource": [
57-
"arn:aws:s3:::your-s3-bucket/backup.tar.gz"
58-
]
59-
}
60-
]
61-
}
47+
"Version": "2012-10-17",
48+
"Statement": [
49+
{
50+
"Sid": "WriteDatabaseBackups",
51+
"Effect": "Allow",
52+
"Action": [
53+
"s3:PutObject",
54+
"s3:AbortMultipartUpload",
55+
"s3:ListMultipartUploadParts"
56+
],
57+
"Resource": ["arn:aws:s3:::your-s3-bucket/backup.tar.gz"]
58+
}
59+
]
60+
}
6261
```
6362

6463

@@ -67,15 +66,17 @@ requirements in a simple way.
6766
1. Launch your database backup worker with `fly apps create --machines`
6867

6968
2. Set the required fly secrets (env vars). Example:
70-
```env
71-
AWS_ACCESS_KEY_ID=XXXX
72-
AWS_SECRET_ACCESS_KEY=XXXX
73-
DATABASE_URL=postgresql://username:password@my-fly-db-instance.internal:5432/my_database
74-
S3_DESTINATION=s3://your-s3-bucket/backup.tar.gz
75-
```
69+
70+
```env
71+
AWS_ACCESS_KEY_ID=XXXX
72+
AWS_SECRET_ACCESS_KEY=XXXX
73+
DATABASE_URL=postgresql://username:password@my-fly-db-instance.internal:5432/my_database
74+
S3_DESTINATION=s3://your-s3-bucket/backup.tar.gz
75+
```
7676

7777
3. OPTION A: Run `./trigger-backup.sh` whenever you want to start a backup.
78-
- `FLY_APP`: (Required) Your fly application.
78+
79+
- `FLY_APP`: (Required) Your fly application.
7980
- `FLY_API_TOKEN`: (Required) Fly token (PAT or Deploy token).
8081
- `FLY_REGION`: the region of the volume and consequently the region where the worker will run.
8182
Choose one close to the db and the AWS bucket region. Defaults to `cdg`.
@@ -87,33 +88,32 @@ requirements in a simple way.
8788
Option to override the default docker image `ghcr.io/significa/fly-pg-dump-to-s3:3`
8889
- `ENSURE_NO_VOLUMES_LEFT`: When the backup completes and the volume is deleted, checks if there
8990
are any volumes still available, and crashes if so. This might be useful to alert that there
90-
are dangling volumes (that you might want to be paying). Defaults to `true`. If you are making
91-
concurrent backups, set it to `false`.
91+
are dangling volumes (that you might want to be paying for).
92+
Defaults to `false` (warning to stderr only).
9293

93-
The volume will be deleted when the backup finishes.
94-
95-
OPTION B: Optionally you can use the reusable GitHub Actions workflow from found in
94+
OPTION B: Call the reusable GitHub Actions workflow found in
9695
`.github/workflows/trigger-backup.yaml`. Example workflow definition:
9796

98-
```yaml
99-
name: Backup databases
100-
on:
101-
workflow_dispatch:
102-
schedule:
103-
# Runs Every day at 5:00am UTC
104-
- cron: "00 5 * * *"
105-
106-
jobs:
107-
backup-databases:
108-
name: Backup databases
109-
uses: significa/fly-pg-dump-to-s3/.github/workflows/trigger-backup.yaml@v3
110-
with:
111-
fly-app: my-db-backup-worker
112-
volume-size: 3
113-
region: ewr
114-
secrets:
115-
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
116-
```
97+
```yaml
98+
name: Backup databases
99+
on:
100+
workflow_dispatch:
101+
schedule:
102+
# Runs Every day at 5:00am UTC
103+
- cron: "00 5 * * *"
104+
105+
jobs:
106+
backup-databases:
107+
name: Backup databases
108+
uses: significa/fly-pg-dump-to-s3/.github/workflows/trigger-backup.yaml@v3
109+
with:
110+
fly-app: my-db-backup-worker
111+
volume-size: 3
112+
machine-size: shared-cpu-4x
113+
region: ewr
114+
secrets:
115+
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
116+
```
117117
118118
119119
## Backup history

trigger-backup.sh

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ FLY_MACHINE_SIZE=${FLY_MACHINE_SIZE:-shared-cpu-4x}
1111
FLY_VOLUME_SIZE=${FLY_VOLUME_SIZE:-3}
1212
DEFAULT_DOCKER_IMAGE="ghcr.io/significa/fly-pg-dump-to-s3:3"
1313
DOCKER_IMAGE=${DOCKER_IMAGE:-$DEFAULT_DOCKER_IMAGE}
14-
ENSURE_NO_VOLUMES_LEFT=${ENSURE_NO_VOLUMES_LEFT-true}
14+
ENSURE_NO_VOLUMES_LEFT=${ENSURE_NO_VOLUMES_LEFT-false}
1515

1616
if [[ -z "$FLY_APP" || -z "$FLY_API_TOKEN" ]]; then
1717
>&2 echo "Env vars FLY_APP and FLY_API_TOKEN must not be empty"
@@ -50,7 +50,7 @@ flyctl machines run \
5050
sleep "$SLEEP_TIME_SECONDS"
5151

5252
echo "Waiting for volume to become detached."
53-
until flyctl volumes show "$volume_id" --json | jq -er '.AttachedMachine == null'; do
53+
until flyctl volumes show "$volume_id" --json | jq -er '.AttachedMachine == null' > /dev/null; do
5454
printf "."
5555
sleep 5
5656
done
@@ -60,9 +60,17 @@ sleep "$SLEEP_TIME_SECONDS"
6060
echo "Deleting volume $volume_id"
6161
flyctl volumes delete --yes "$volume_id"
6262

63-
if "$ENSURE_NO_VOLUMES_LEFT" && fly volumes list --app="$FLY_APP" --json | jq -e 'length != 0' ; then
64-
>&2 echo "Backup completed but the app still has volumes. ENSURE_NO_VOLUMES_LEFT is true, exiting"
65-
exit 1
63+
sleep "$SLEEP_TIME_SECONDS"
64+
65+
volumes_left=$(fly volumes list --app="$FLY_APP" --json)
66+
67+
if jq -e 'length != 0' <<< "$volumes_left" > /dev/null ; then
68+
>&2 echo -e "WARNING: Backup completed but the app still has volumes. Response:\n$volumes_left"
69+
70+
if "$ENSURE_NO_VOLUMES_LEFT" ; then
71+
>&2 echo "ERROR: ENSURE_NO_VOLUMES_LEFT is true, exiting."
72+
exit 1
73+
fi
6674
fi
6775

6876
echo "Done"

0 commit comments

Comments
 (0)