From f97ce11734c8309213eb96e446426ec6d5d30eda Mon Sep 17 00:00:00 2001 From: "J. Zebedee" Date: Sun, 11 Aug 2024 03:11:09 -0500 Subject: [PATCH] Add "none" compression type (#457) * Add "none" compression type * Add "none" compression to docs * Use passThroughWriteCloser for "none" compression * Add test for none compression --------- Co-authored-by: Frederik Ring --- cmd/backup/archive.go | 14 ++++++++++++++ cmd/backup/config.go | 2 +- cmd/backup/script.go | 7 ++++++- docs/reference/index.md | 6 +++--- test/tar/docker-compose.yml | 21 +++++++++++++++++++++ test/tar/run.sh | 25 +++++++++++++++++++++++++ 6 files changed, 70 insertions(+), 5 deletions(-) create mode 100644 test/tar/docker-compose.yml create mode 100755 test/tar/run.sh diff --git a/cmd/backup/archive.go b/cmd/backup/archive.go index 87b3466..61f6829 100644 --- a/cmd/backup/archive.go +++ b/cmd/backup/archive.go @@ -93,6 +93,8 @@ func compress(paths []string, outFilePath, algo string, concurrency int) error { func getCompressionWriter(file *os.File, algo string, concurrency int) (io.WriteCloser, error) { switch algo { + case "none": + return &passThroughWriteCloser{file}, nil case "gz": w, err := pgzip.NewWriterLevel(file, 5) if err != nil { @@ -165,3 +167,15 @@ func writeTarball(path string, tarWriter *tar.Writer, prefix string) error { return nil } + +type passThroughWriteCloser struct { + target io.WriteCloser +} + +func (p *passThroughWriteCloser) Write(b []byte) (int, error) { + return p.target.Write(b) +} + +func (p *passThroughWriteCloser) Close() error { + return nil +} diff --git a/cmd/backup/config.go b/cmd/backup/config.go index 0fb16de..0609a2f 100644 --- a/cmd/backup/config.go +++ b/cmd/backup/config.go @@ -92,7 +92,7 @@ type CompressionType string func (c *CompressionType) Decode(v string) error { switch v { - case "gz", "zst": + case "none", "gz", "zst": *c = CompressionType(v) return nil default: diff --git a/cmd/backup/script.go b/cmd/backup/script.go index d947e11..56b8af8 100644 --- a/cmd/backup/script.go +++ b/cmd/backup/script.go @@ -86,7 +86,12 @@ func (s *script) init() error { var bf bytes.Buffer if tErr := tmplFileName.Execute(&bf, map[string]string{ - "Extension": fmt.Sprintf("tar.%s", s.c.BackupCompression), + "Extension": func() string { + if s.c.BackupCompression == "none" { + return "tar" + } + return fmt.Sprintf("tar.%s", s.c.BackupCompression) + }(), }); tErr != nil { return errwrap.Wrap(tErr, "error executing backup file extension template") } diff --git a/docs/reference/index.md b/docs/reference/index.md index ffd76ce..40146d8 100644 --- a/docs/reference/index.md +++ b/docs/reference/index.md @@ -43,8 +43,8 @@ You can populate below template according to your requirements and use it as you # BACKUP_CRON_EXPRESSION="0 2 * * *" # The compression algorithm used in conjunction with tar. -# Valid options are: "gz" (Gzip) and "zst" (Zstd). -# Note that the selection affects the file extension. +# Valid options are: "gz" (Gzip), "zst" (Zstd) or "none" (tar only). +# Default is "gz". Note that the selection affects the file extension. # BACKUP_COMPRESSION="gz" @@ -60,7 +60,7 @@ You can populate below template according to your requirements and use it as you # will result in the same filename for every backup run, which means previous # versions will be overwritten on subsequent runs. # Extension can be defined literally or via "{{ .Extension }}" template, -# in which case it will become either "tar.gz" or "tar.zst" (depending +# in which case it will become either "tar.gz", "tar.zst" or ".tar" (depending # on your BACKUP_COMPRESSION setting). # The default results in filenames like: `backup-2021-08-29T04-00-00.tar.gz`. diff --git a/test/tar/docker-compose.yml b/test/tar/docker-compose.yml new file mode 100644 index 0000000..a3f7aa7 --- /dev/null +++ b/test/tar/docker-compose.yml @@ -0,0 +1,21 @@ +services: + backup: + image: offen/docker-volume-backup:${TEST_VERSION:-canary} + restart: always + environment: + BACKUP_FILENAME: test.{{ .Extension }} + BACKUP_COMPRESSION: none + volumes: + - app_data:/backup/app_data:ro + - /var/run/docker.sock:/var/run/docker.sock + - ${LOCAL_DIR:-./local}:/archive + + offen: + image: offen/offen:latest + labels: + - docker-volume-backup.stop-during-backup=true + volumes: + - app_data:/var/opt/offen + +volumes: + app_data: diff --git a/test/tar/run.sh b/test/tar/run.sh new file mode 100755 index 0000000..7d8d89d --- /dev/null +++ b/test/tar/run.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +set -e + +cd "$(dirname "$0")" +. ../util.sh +current_test=$(basename $(pwd)) + +export LOCAL_DIR=$(mktemp -d) + +docker compose up -d --quiet-pull +sleep 5 + +docker compose exec backup backup + +sleep 5 + +expect_running_containers "2" + +tmp_dir=$(mktemp -d) +tar -xvf "$LOCAL_DIR/test.tar" -C $tmp_dir +if [ ! -f "$tmp_dir/backup/app_data/offen.db" ]; then + fail "Could not find expected file in untared archive." +fi +pass "Expected file was found."