diff --git a/README.md b/README.md index f66f36f..1f372be 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # youtrack-backup -Perl script to create a backup of the YouTrack Cloud database and store -it in a Backblaze B2 bucket. +Perl script to create a backup of the YouTrack Cloud database, store +it in a Backblaze B2 bucket, and optionally delete old backup files. ## Environment variables * `YT_TOKEN` - YouTrack permanent access token @@ -11,6 +11,7 @@ it in a Backblaze B2 bucket. * `--baseurl` - YouTrack Cloud URL. * `--bucket` - Backblaze bucket name. * `--delay` - [optional] Seconds to wait between checks for database backup completion. (Default: 30) +* `--keep` - [optional] Number of backup files to keep. (Default: 0, keep all backup files) * `--quiet` - [optional] Don't print information progress messages. * `--help` - [optional] Print usage message and exit. @@ -53,8 +54,9 @@ youtrack-backup.pl --baseurl _yt-url_ --bucket _b2-bucket-name_ ### Additional environment variables * `YT_URL` - URL to your instance of YouTrack Cloud. * `B2_BUCKET` - Name of the Backblaze B2 bucket. +* `KEEP_COUNT` - Number of backups to keep. -The image created by the Dockerfile will run `youtrack-backup.pl` with `--delay` defaulted to `30` and `--quiet` disabled. +The image created by the Dockerfile will run `youtrack-backup.pl` with `--delay` defaulted to `30`, `--keep` defaulted to `0`, and `--quiet` disabled. 1. Copy `local.env.dist` to `local.env`. 1. Set the values for the variables contained in `local.env`. diff --git a/local.env.dist b/local.env.dist index d88846c..3bcc78c 100644 --- a/local.env.dist +++ b/local.env.dist @@ -1,5 +1,6 @@ B2_APPLICATION_KEY_ID= B2_APPLICATION_KEY= B2_BUCKET= +KEEP_COUNT= YT_TOKEN= YT_URL= diff --git a/youtrack-backup.pl b/youtrack-backup.pl index 7a813fc..3f4bc55 100755 --- a/youtrack-backup.pl +++ b/youtrack-backup.pl @@ -6,10 +6,10 @@ # export YT_TOKEN= # export B2_APPLICATION_KEY_ID= # export B2_APPLICATION_KEY= -# youtrack-db-backup.pl --baseurl=yt-url --bucket=b2-bucket-name [--delay=seconds] [--quiet] [--help] +# youtrack-db-backup.pl --baseurl=yt-url --bucket=b2-bucket-name [--delay=seconds] [--keep=count] [--quiet] [--help] # # For the supplied YouTrack instance (baseurl), create a database backup and -# store it in a Backblaze B2 bucket. +# store it in a Backblaze B2 bucket. Optionally, delete old backup files. # # Uses curl(1), jq(1), b2(https://www.backblaze.com/docs/cloud-storage-command-line-tools). # @@ -28,13 +28,14 @@ () return strftime "%H:%M:%S", gmtime; } -my $usage = "Usage: $0 --baseurl=yt-url --bucket=b2-bucket-name [--delay=seconds] [--quiet] [--help]\n"; +my $usage = "Usage: $0 --baseurl=yt-url --bucket=b2-bucket-name [--delay=seconds] [--keep=count] [--quiet] [--help]\n"; my $yt_token; # YouTrack Permanent Token my $yt_url; # YouTrack base URL my $b2_app_key_id; # Backblaze application key ID my $b2_app_key_secret; # Backblaze application key secret my $b2_bucket; # Backblaze B2 bucket name my $delay; # seconds to delay between checking backup progress +my $keep_count; # number of backup files to keep my $quiet; my $help; @@ -43,6 +44,7 @@ () 'bucket|b=s' => \$b2_bucket, 'baseurl|u=s' => \$yt_url, 'delay|d' => \$delay, + 'keep|k=i' => \$keep_count, 'quiet|q' => \$quiet, 'help|h' => \$help ) or die $usage; @@ -78,7 +80,8 @@ () my $content_header = "--header \"Content-Type: application/json\""; my $progress_header = "--no-progress-meter"; -$delay = 30 if (! defined($delay)); +$delay = 30 if (! defined($delay)); +$keep_count = 0 if (! defined($keep_count)); my $curl_query1; my $curl_query2; @@ -192,4 +195,40 @@ () unlink($download_path); +# +# Optionally, delete old backup files from the Backblaze B2 bucket +# +# The backup file names are of the form YYYY-MM-DD-hh-mm-ss.tar.gz. The +# 'b2 ls --long' command returns lines in this form: +# +# fileID upload date time size fileName +# +# We keep the sixth and first fields, sort, and throw away the last $keep_count +# entries. The remaining files (if any) will be deleted. + +if ($keep_count > 0) { + printf "%s: Deleting old backup files\n", tstamp() if (! $quiet); + $cmd = "b2 ls --long $b2_bucket"; + my @filelist = `$cmd`; + + if (scalar @filelist - ${keep_count} > 0) { + chomp @filelist; + s/ .* / / for @filelist; # keep only first and last fields + s/^(.*) (.*)$/$2 $1/ for @filelist; # swap order of fields + + @filelist = sort @filelist; + splice @filelist, -${keep_count}; + + foreach my $line (@filelist) { + (my $filename, my $fileid) = split / /,$line; + printf "%s: Deleting $filename\n", tstamp() if (! $quiet); + $cmd = "b2 delete-file-version $filename $fileid"; + $result = system($cmd); + } + } + else { + printf "%s: Number of files (%d) does not exceed the number to keep ($keep_count)\n", tstamp(), scalar @filelist if (! $quiet); + } +} + exit(0); diff --git a/youtrack-backup.sh b/youtrack-backup.sh index fe96400..de83b72 100755 --- a/youtrack-backup.sh +++ b/youtrack-backup.sh @@ -1,4 +1,4 @@ #!/bin/sh -youtrack-backup.pl --baseurl $YT_URL --bucket $B2_BUCKET +youtrack-backup.pl --baseurl $YT_URL --bucket $B2_BUCKET --keep $KEEP_COUNT