From 0f7c519bc3a28292817f67babe1d14a286e88e72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sandro=20J=C3=A4ckel?= Date: Wed, 13 Sep 2023 15:33:46 +0200 Subject: [PATCH] Use pgdump matching postgresql server version --- Dockerfile | 2 +- Makefile.maker.yaml | 9 ++++++--- internal/backup/backup.go | 24 +++++++++++++++++++++++- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index a562df35..ef7ba989 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,7 +14,7 @@ RUN addgroup -g 4200 appgroup \ && adduser -h /home/appuser -s /sbin/nologin -G appgroup -D -u 4200 appuser # upgrade all installed packages to fix potential CVEs in advance RUN apk upgrade --no-cache --no-progress \ - && apk add --no-cache --no-progress ca-certificates postgresql15-client curl jq + && apk add --no-cache --no-progress ca-certificates postgresql12-client postgresql15-client curl jq COPY --from=builder /pkg/ /usr/ ARG BININFO_BUILD_DATE BININFO_COMMIT_HASH BININFO_VERSION diff --git a/Makefile.maker.yaml b/Makefile.maker.yaml index eec46efd..7e57c423 100644 --- a/Makefile.maker.yaml +++ b/Makefile.maker.yaml @@ -14,9 +14,12 @@ dockerfile: extraDirectives: - "ENV ENV=/usr/bin/motd.sh" # `kubectl exec` is not a login shell, so we need to use this instead of /etc/profile or $HOME/.profile extraPackages: - - postgresql15-client # for psql, pg_dump - - curl # required for backup-tools.sh - - jq # required for backup-tools.sh + # for psql, pg_dump + - postgresql12-client + - postgresql15-client + # required for backup-tools.sh + - curl + - jq golang: enableVendoring: true diff --git a/internal/backup/backup.go b/internal/backup/backup.go index ba9a0aa7..8bca89c4 100644 --- a/internal/backup/backup.go +++ b/internal/backup/backup.go @@ -21,6 +21,7 @@ package backup import ( "context" + "errors" "fmt" "io" "os" @@ -54,6 +55,10 @@ const ( retentionTime time.Duration = 10 * 24 * time.Hour // 10 days ) +func getPgdumpForVersion(majorVersion string) string { + return fmt.Sprintf("/usr/libexec/postgresql%s/pg_dump", majorVersion) +} + // Create creates a backup unconditionally. The provided `reason` is used // in log messages to explain why the backup was created. func Create(cfg *core.Configuration, reason string) (nowTime time.Time, returnedError error) { @@ -90,12 +95,29 @@ func Create(cfg *core.Configuration, reason string) (nowTime time.Time, returned //Close() the writer side in order for LargeObject.Append() to return on //the reader side. + // determine postgresql server version + cmd := exec.CommandContext(ctx, "psql", //nolint:gosec // input is user supplied and self executed + "-h", cfg.PgHostname, "-U", cfg.PgUsername, //NOTE: PGPASSWORD comes via inherited env variable + "--csv", "--tuples-only", "-c", "SHOW SERVER_VERSION") // output not decoration or padding + output, err := cmd.Output() + if err != nil { + return nowTime, fmt.Errorf("could not determine postgresql server version: %w", err) + } + + majorVersion := strings.Split(string(output), ".")[0] + pgdump := getPgdumpForVersion(majorVersion) + + // if the pgdump version was not found fallback to pgdump version 12 + if _, err := os.Stat(pgdump); errors.Is(err, os.ErrNotExist) { + pgdump = getPgdumpForVersion("12") + } + //run pg_dump pipeReader, pipeWriter := io.Pipe() errChan := make(chan error, 1) //must be buffered to ensure that `pipewriter.Close()` runs immediately go func() { defer pipeWriter.Close() - cmd := exec.CommandContext(ctx, "pg_dump", //nolint:gosec // input is user supplied and self executed + cmd := exec.CommandContext(ctx, pgdump, "-h", cfg.PgHostname, "-U", cfg.PgUsername, //NOTE: PGPASSWORD comes via inherited env variable "-c", "--if-exist", "-C", "-Z", "5", databaseName) logg.Info(">> " + shellquote.Join(cmd.Args...))