Skip to content

Commit 0b8491d

Browse files
committed
feat: support custom params and parallelism for restore (#6)
All other basic operations already support custom flags. Even the restore itself is supposed to already support them but, as opposed to Barman, pgBackRest has two separate commands used during the restore: * restore (responsible for downloading and applying the main backup), * archive-get (responsible for PITR part - retrieving necessary WAL files later than the backup itself). Currently only the archive-get part is customizable. Especially painful is the inability to configure parallelism as that means the main backup can take very long time to download, hence a dedicated field for it (just like for backups). Signed-off-by: Szymon Soloch <[email protected]>
1 parent 2947174 commit 0b8491d

File tree

16 files changed

+474
-79
lines changed

16 files changed

+474
-79
lines changed

config/crd/bases/pgbackrest.cnpg.opera.com_archives.yaml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,31 @@ spec:
283283
- destinationPath
284284
type: object
285285
type: array
286+
restore:
287+
description: The configuration to be used to restore the data
288+
files
289+
properties:
290+
additionalCommandArgs:
291+
description: |-
292+
AdditionalCommandArgs represents additional arguments that can be appended
293+
to the 'pgbackrest restore' command-line invocation. These arguments
294+
provide flexibility to customize the restore process further according to
295+
specific requirements or configurations.
296+
297+
Note:
298+
It's essential to ensure that the provided arguments are valid and supported
299+
by the 'pgbackrest restore' command, to avoid potential errors or unintended
300+
behavior during execution.
301+
items:
302+
type: string
303+
type: array
304+
jobs:
305+
description: The number of parallel jobs to be used to download
306+
the main backup.
307+
format: int32
308+
minimum: 1
309+
type: integer
310+
type: object
286311
stanza:
287312
description: |-
288313
Pgbackrest stanza (name used in the archive store), the cluster name is used if

internal/cnpgi/common/wal.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ func (w WALServiceImplementation) restoreFromPgbackrestArchive(
244244

245245
// Create the restorer
246246
var walRestorer *pgbackrestRestorer.WALRestorer
247-
if walRestorer, err = pgbackrestRestorer.New(ctx, env, w.SpoolDirectory); err != nil {
247+
if walRestorer, err = pgbackrestRestorer.NewWALRestorer(ctx, env, w.SpoolDirectory); err != nil {
248248
return fmt.Errorf("while creating the restorer: %w", err)
249249
}
250250

internal/cnpgi/operator/reconciler.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ func (r ReconcilerImplementation) ensureRole(
184184
"namespace", newRole.Namespace,
185185
"rules", newRole.Rules,
186186
)
187-
187+
// TODO: Something is wrong here, we also should check for ownership.
188188
return r.Client.Patch(ctx, newRole, client.MergeFrom(&role))
189189
}
190190

internal/cnpgi/restore/restore.go

Lines changed: 3 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,15 @@ package restore
1919

2020
import (
2121
"context"
22-
"errors"
2322
"fmt"
2423
"os"
25-
"os/exec"
2624
"path"
2725
"time"
2826

2927
cnpgv1 "github.com/cloudnative-pg/cloudnative-pg/api/v1"
3028
"github.com/cloudnative-pg/cloudnative-pg/pkg/postgres"
3129
"github.com/cloudnative-pg/cloudnative-pg/pkg/utils"
3230
restore "github.com/cloudnative-pg/cnpg-i/pkg/restore/job"
33-
"github.com/cloudnative-pg/machinery/pkg/execlog"
3431
"github.com/cloudnative-pg/machinery/pkg/fileutils"
3532
"github.com/cloudnative-pg/machinery/pkg/log"
3633
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -153,63 +150,12 @@ func (impl JobHookImpl) restoreDataDir(
153150
env []string,
154151
pgbackrestConfiguration *pgbackrestApi.PgbackrestConfiguration,
155152
) error {
156-
var options []string
157-
158-
if backup.Status.EndpointURL != "" {
159-
options = append(options, "--endpoint-url", backup.Status.EndpointURL)
160-
}
161-
162-
options = append(
163-
options,
164-
"--stanza", backup.Status.ServerName,
165-
"--lock-path",
166-
"/controller/tmp/pgbackrest")
167-
168-
options, err := pgbackrestCommand.AppendCloudProviderOptionsFromConfiguration(ctx, options, pgbackrestConfiguration)
169-
if err != nil {
170-
return err
171-
}
172-
173-
options, err = pgbackrestCommand.AppendLogOptionsFromConfiguration(ctx, options, pgbackrestConfiguration)
174-
if err != nil {
175-
return err
176-
}
177-
178-
options, err = pgbackrestCommand.AppendStanzaOptionsFromConfiguration(
179-
ctx,
180-
options,
153+
restoreCmd := pgbackrestRestorer.NewRestoreCommand(
181154
pgbackrestConfiguration,
182155
impl.PgDataPath,
183-
false,
184156
)
185-
if err != nil {
186-
return err
187-
}
188-
189-
options = append(
190-
options,
191-
"restore",
192-
"--set",
193-
backup.Status.BackupID,
194-
)
195-
196-
log.Info("Starting pgbackrest restore",
197-
"options", options)
198157

199-
cmd := exec.Command("pgbackrest", options...) // #nosec G204
200-
cmd.Env = env
201-
err = execlog.RunStreaming(cmd, "pgbackrest restore")
202-
if err != nil {
203-
var exitError *exec.ExitError
204-
if errors.As(err, &exitError) {
205-
err = pgbackrestCommand.UnmarshalPgbackrestRestoreExitCode(ctx, exitError.ExitCode())
206-
}
207-
208-
log.Error(err, "Can't restore backup")
209-
return err
210-
}
211-
log.Info("Restore completed")
212-
return nil
158+
return restoreCmd.Restore(ctx, backup.Status.BackupID, backup.Status.ServerName, env)
213159
}
214160

215161
// TODO: Likely doesn't make sense for pgbackrest. Might be tricky to implement properly.
@@ -234,7 +180,7 @@ func (impl JobHookImpl) ensureArchiveContainsLastCheckpointRedoWAL(
234180
return err
235181
}
236182

237-
rest, err := pgbackrestRestorer.New(
183+
rest, err := pgbackrestRestorer.NewWALRestorer(
238184
ctx,
239185
env,
240186
impl.SpoolDirectory,

internal/pgbackrest/api/config.go

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,28 @@ type DataBackupConfiguration struct {
236236
AdditionalCommandArgs []string `json:"additionalCommandArgs,omitempty"`
237237
}
238238

239+
// DataRestoreConfiguration is the configuration of the main backup restore process
240+
// (pgbackrest restore call) which is then followed by a series of WAL restore
241+
// (pgbackrest archive-get) calls using the WalBackupConfiguration
242+
type DataRestoreConfiguration struct {
243+
// The number of parallel jobs to be used to download the main backup.
244+
// +kubebuilder:validation:Minimum=1
245+
// +optional
246+
Jobs *int32 `json:"jobs,omitempty"`
247+
248+
// AdditionalCommandArgs represents additional arguments that can be appended
249+
// to the 'pgbackrest restore' command-line invocation. These arguments
250+
// provide flexibility to customize the restore process further according to
251+
// specific requirements or configurations.
252+
//
253+
// Note:
254+
// It's essential to ensure that the provided arguments are valid and supported
255+
// by the 'pgbackrest restore' command, to avoid potential errors or unintended
256+
// behavior during execution.
257+
// +optional
258+
AdditionalCommandArgs []string `json:"additionalCommandArgs,omitempty"`
259+
}
260+
239261
// PgbackrestRepository contains configuration of a single Pgbackrest backup target
240262
// repository, including all data needed to properly connect and authenticate with
241263
// a selected object store.
@@ -298,6 +320,10 @@ type PgbackrestConfiguration struct {
298320
// +optional
299321
Data *DataBackupConfiguration `json:"data,omitempty"`
300322

323+
// The configuration to be used to restore the data files
324+
// +optional
325+
Restore *DataRestoreConfiguration `json:"restore,omitempty"`
326+
301327
// Compress a WAL file before sending it to the object store. Available
302328
// options are empty string (no compression, default), `gz`, `bz2`, `lz4` or 'zst'.
303329
// +kubebuilder:validation:Enum=gz;bz2;lz4;zst
@@ -316,8 +342,16 @@ func (credentials PgbackrestCredentials) ArePopulated() bool {
316342
return credentials.AWS != nil
317343
}
318344

319-
// AppendRestoreAdditionalCommandArgs adds custom arguments as pgbackrest restore command-line options
320-
func (cfg *WalBackupConfiguration) AppendRestoreAdditionalCommandArgs(options []string) []string {
345+
// AppendAdditionalRestoreCommandArgs adds custom arguments as pgbackrest restore command-line options
346+
func (cfg *DataRestoreConfiguration) AppendAdditionalRestoreCommandArgs(options []string) []string {
347+
if cfg == nil || len(cfg.AdditionalCommandArgs) == 0 {
348+
return options
349+
}
350+
return appendAdditionalCommandArgs(cfg.AdditionalCommandArgs, options)
351+
}
352+
353+
// AppendAdditionalArchiveGetCommandArgs adds custom arguments as pgbackrest archive-get command-line options
354+
func (cfg *WalBackupConfiguration) AppendAdditionalArchiveGetCommandArgs(options []string) []string {
321355
if cfg == nil || len(cfg.RestoreAdditionalCommandArgs) == 0 {
322356
return options
323357
}
@@ -342,16 +376,16 @@ func appendAdditionalCommandArgs(additionalCommandArgs []string, options []strin
342376
return options
343377
}
344378

345-
// AppendAdditionalCommandArgs adds custom arguments as pgbackrest backup command-line options
346-
func (cfg *DataBackupConfiguration) AppendAdditionalCommandArgs(options []string) []string {
379+
// AppendAdditionalBackupCommandArgs adds custom arguments as pgbackrest backup command-line options
380+
func (cfg *DataBackupConfiguration) AppendAdditionalBackupCommandArgs(options []string) []string {
347381
if cfg == nil || len(cfg.AdditionalCommandArgs) == 0 {
348382
return options
349383
}
350384
return appendAdditionalCommandArgs(cfg.AdditionalCommandArgs, options)
351385
}
352386

353-
// AppendArchiveAdditionalCommandArgs adds custom arguments as pgbackrest archive-push command-line options
354-
func (cfg *WalBackupConfiguration) AppendArchiveAdditionalCommandArgs(options []string) []string {
387+
// AppendAdditionalArchivePushCommandArgs adds custom arguments as pgbackrest archive-push command-line options
388+
func (cfg *WalBackupConfiguration) AppendAdditionalArchivePushCommandArgs(options []string) []string {
355389
if cfg == nil || len(cfg.ArchiveAdditionalCommandArgs) == 0 {
356390
return options
357391
}

internal/pgbackrest/api/config_test.go

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import (
2222
. "github.com/onsi/gomega"
2323
)
2424

25-
var _ = Describe("DataBackupConfiguration.AppendAdditionalCommandArgs", func() {
25+
var _ = Describe("DataBackupConfiguration.AppendAdditionalBackupCommandArgs", func() {
2626
var options []string
2727
var config DataBackupConfiguration
2828
BeforeEach(func() {
@@ -33,35 +33,79 @@ var _ = Describe("DataBackupConfiguration.AppendAdditionalCommandArgs", func() {
3333
})
3434

3535
It("should append additional command args to the options", func() {
36-
updatedOptions := config.AppendAdditionalCommandArgs(options)
36+
updatedOptions := config.AppendAdditionalBackupCommandArgs(options)
3737
Expect(updatedOptions).To(Equal([]string{"--option1", "--option2", "--option3", "--option4"}))
3838
})
3939

4040
It("should return the original options if there are no additional command args", func() {
4141
config.AdditionalCommandArgs = nil
42-
updatedOptions := config.AppendAdditionalCommandArgs(options)
42+
updatedOptions := config.AppendAdditionalBackupCommandArgs(options)
4343
Expect(updatedOptions).To(Equal(options))
4444
})
4545
})
4646

47-
var _ = Describe("WalBackupConfiguration.AppendAdditionalCommandArgs", func() {
47+
var _ = Describe("DataBackupConfiguration.AppendAdditionalRestoreCommandArgs", func() {
4848
var options []string
49-
var config DataBackupConfiguration
49+
var config DataRestoreConfiguration
5050
BeforeEach(func() {
5151
options = []string{"--option1", "--option2"}
52-
config = DataBackupConfiguration{
52+
config = DataRestoreConfiguration{
5353
AdditionalCommandArgs: []string{"--option3", "--option4"},
5454
}
5555
})
5656

5757
It("should append additional command args to the options", func() {
58-
updatedOptions := config.AppendAdditionalCommandArgs(options)
58+
updatedOptions := config.AppendAdditionalRestoreCommandArgs(options)
5959
Expect(updatedOptions).To(Equal([]string{"--option1", "--option2", "--option3", "--option4"}))
6060
})
6161

6262
It("should return the original options if there are no additional command args", func() {
6363
config.AdditionalCommandArgs = nil
64-
updatedOptions := config.AppendAdditionalCommandArgs(options)
64+
updatedOptions := config.AppendAdditionalRestoreCommandArgs(options)
65+
Expect(updatedOptions).To(Equal(options))
66+
})
67+
})
68+
69+
var _ = Describe("WalBackupConfiguration.AppendAdditionalArchivePushCommandArgs", func() {
70+
var options []string
71+
var config WalBackupConfiguration
72+
BeforeEach(func() {
73+
options = []string{"--option1", "--option2"}
74+
config = WalBackupConfiguration{
75+
ArchiveAdditionalCommandArgs: []string{"--option3", "--option4"},
76+
}
77+
})
78+
79+
It("should append additional command args to the options", func() {
80+
updatedOptions := config.AppendAdditionalArchivePushCommandArgs(options)
81+
Expect(updatedOptions).To(Equal([]string{"--option1", "--option2", "--option3", "--option4"}))
82+
})
83+
84+
It("should return the original options if there are no additional command args", func() {
85+
config.ArchiveAdditionalCommandArgs = nil
86+
updatedOptions := config.AppendAdditionalArchivePushCommandArgs(options)
87+
Expect(updatedOptions).To(Equal(options))
88+
})
89+
})
90+
91+
var _ = Describe("WalBackupConfiguration.AppendAdditionalArchiveGetCommandArgs", func() {
92+
var options []string
93+
var config WalBackupConfiguration
94+
BeforeEach(func() {
95+
options = []string{"--option1", "--option2"}
96+
config = WalBackupConfiguration{
97+
RestoreAdditionalCommandArgs: []string{"--option3", "--option4"},
98+
}
99+
})
100+
101+
It("should append additional command args to the options", func() {
102+
updatedOptions := config.AppendAdditionalArchiveGetCommandArgs(options)
103+
Expect(updatedOptions).To(Equal([]string{"--option1", "--option2", "--option3", "--option4"}))
104+
})
105+
106+
It("should return the original options if there are no additional command args", func() {
107+
config.RestoreAdditionalCommandArgs = nil
108+
updatedOptions := config.AppendAdditionalArchiveGetCommandArgs(options)
65109
Expect(updatedOptions).To(Equal(options))
66110
})
67111
})

internal/pgbackrest/api/zz_generated.deepcopy.go

Lines changed: 30 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/pgbackrest/archiver/command.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ func (archiver *WALArchiver) PgbackrestWalArchiveOptions(
129129
// }
130130

131131
if configuration.Wal != nil {
132-
options = configuration.Wal.AppendArchiveAdditionalCommandArgs(options)
132+
options = configuration.Wal.AppendAdditionalArchivePushCommandArgs(options)
133133
}
134134

135135
options, err = pgbackrestCommand.AppendCloudProviderOptionsFromConfiguration(ctx, options, configuration)

internal/pgbackrest/backup/backup.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ func (b *Command) GetDataConfiguration(
8888
strconv.Itoa(int(*b.configuration.Data.Jobs)))
8989
}
9090

91-
return b.configuration.Data.AppendAdditionalCommandArgs(options), nil
91+
return b.configuration.Data.AppendAdditionalBackupCommandArgs(options), nil
9292
}
9393

9494
// GetPgbackrestBackupOptions extract the list of command line options to be used with

internal/pgbackrest/command/commandbuilder.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ func CloudWalRestoreOptions(
5151
"--stanza",
5252
stanza)
5353

54-
options = configuration.Wal.AppendRestoreAdditionalCommandArgs(options)
54+
options = configuration.Wal.AppendAdditionalArchiveGetCommandArgs(options)
5555

5656
return options, nil
5757
}

0 commit comments

Comments
 (0)