Skip to content

Commit 71137c9

Browse files
committed
Added backup subcommand and refactored backup and restore jobs
1 parent 1512c2d commit 71137c9

20 files changed

+618
-591
lines changed

.vscode/launch.json

+12-11
Original file line numberDiff line numberDiff line change
@@ -71,33 +71,34 @@
7171
],
7272
},
7373
{
74-
"name": "PITR",
74+
"name": "Backup",
7575
"type": "go",
7676
"request": "launch",
7777
"mode": "auto",
7878
"program": "cmd/controller",
7979
"args": [
80-
"pitr",
81-
"--backup-path=backup",
82-
"--result-file-path=backup/0-point-in-time-recovery.txt",
83-
"--target-recovery-time=1970-01-01T00:00:00Z",
80+
"backup",
81+
"--path=backup",
82+
"--target-time=1970-01-01T00:00:00Z",
83+
"--target-file-path=backup/0-backup-target.txt",
8484
"--log-dev",
8585
"--log-level=debug",
8686
"--log-time-encoder=iso8601",
8787
],
8888
"cwd": "${workspaceRoot}"
8989
},
9090
{
91-
"name": "PITR Enterprise",
91+
"name": "Restore",
9292
"type": "go",
9393
"request": "launch",
9494
"mode": "auto",
95-
"program": "cmd/enterprise",
95+
"program": "cmd/controller",
9696
"args": [
97-
"pitr",
98-
"--backup-path=backup",
99-
"--result-file-path=backup/0-point-in-time-recovery.txt",
100-
"--target-recovery-time=1970-01-01T00:00:00Z",
97+
"backup",
98+
"restore",
99+
"--path=backup",
100+
"--target-time=1970-01-01T00:00:00Z",
101+
"--target-file-path=backup/0-backup-target.txt",
101102
"--log-dev",
102103
"--log-level=debug",
103104
"--log-time-encoder=iso8601",

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ Run and operate MariaDB in a cloud native way. Declaratively manage your MariaDB
2424
- [Provisioning](./examples/manifests/mariadb_v1alpha1_mariadb.yaml) highly configurable MariaDB servers.
2525
- Multiple [HA modes](./docs/HA.md) supported: [SemiSync Replication](./examples/manifests/mariadb_v1alpha1_mariadb_replication.yaml) and [Galera](./docs/GALERA.md). Automatic primary failover.
2626
- [Take](./examples/manifests/mariadb_v1alpha1_backup.yaml) and [restore](./examples/manifests/mariadb_v1alpha1_restore.yaml) backups. [Scheduled](./examples/manifests/mariadb_v1alpha1_backup_scheduled.yaml) backups. Backup rotation
27-
- [Point in time recovery](./examples/manifests/mariadb_v1alpha1_restore_target_recovery_time.yaml) (PITR)
27+
- [Point in time recovery](./examples/manifests/mariadb_v1alpha1_restore_point_in_time_recovery.yaml) (PITR)
2828
- [PVCs](./examples/manifests/mariadb_v1alpha1_backup.yaml) and all Kubernetes-compatible [volumes](https://kubernetes.io/docs/concepts/storage/volumes/#volume-types) (i.e. [NFS](./examples/manifests/mariadb_v1alpha1_backup_nfs.yaml)) supported as backup storage
2929
- Bootstrap new instances from [backups](./examples/manifests/mariadb_v1alpha1_mariadb_from_backup.yaml) and volumes (i.e [NFS](./examples/manifests/mariadb_v1alpha1_mariadb_from_nfs.yaml))
3030
- [Prometheus metrics](./docs/METRICS.md) via [mysqld-exporter](https://github.com/prometheus/mysqld_exporter) as a multi-target Deployment

api/v1alpha1/base_types.go

+8
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package v1alpha1
22

33
import (
44
"errors"
5+
"time"
56

67
"github.com/mariadb-operator/mariadb-operator/pkg/webhook"
78
cron "github.com/robfig/cron/v3"
@@ -265,6 +266,13 @@ func (r *RestoreSource) Validate() error {
265266
return nil
266267
}
267268

269+
func (r *RestoreSource) TargetRecoveryTimeOrDefault() time.Time {
270+
if r.TargetRecoveryTime != nil {
271+
return r.TargetRecoveryTime.Time
272+
}
273+
return time.Now()
274+
}
275+
268276
// Schedule contains parameters to define a schedule
269277
type Schedule struct {
270278
// Cron is a cron expression that defines the schedule.

cmd/backup/backup.go

-48
This file was deleted.

cmd/backup/main.go

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package backup
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"time"
7+
8+
"github.com/mariadb-operator/mariadb-operator/pkg/backup"
9+
"github.com/mariadb-operator/mariadb-operator/pkg/log"
10+
"github.com/spf13/cobra"
11+
ctrl "sigs.k8s.io/controller-runtime"
12+
)
13+
14+
var (
15+
logger = ctrl.Log
16+
path string
17+
targetFilePath string
18+
targetTimeRaw string
19+
)
20+
21+
func init() {
22+
RootCmd.PersistentFlags().StringVar(&path, "path", "/backup", "Directory path where the backup files are located.")
23+
RootCmd.PersistentFlags().StringVar(&targetTimeRaw, "target-time", "",
24+
"RFC3339 (1970-01-01T00:00:00Z) date and time that defines the backup target time.")
25+
RootCmd.PersistentFlags().StringVar(&targetFilePath, "target-file-path", "/backup/0-backup-target.txt",
26+
"Path to a file that contains the name of the backup target file.")
27+
28+
RootCmd.AddCommand(restoreCommand)
29+
}
30+
31+
var RootCmd = &cobra.Command{
32+
Use: "backup",
33+
Short: "Backup.",
34+
Long: `Manages the backed up files in order to be compliant with the retention policy.`,
35+
Args: cobra.NoArgs,
36+
Run: func(cmd *cobra.Command, args []string) {
37+
if err := setupLogger(cmd); err != nil {
38+
fmt.Printf("error setting up logger: %v\n", err)
39+
os.Exit(1)
40+
}
41+
logger.Info("Starting backup")
42+
43+
targetTime, err := getTargetTime()
44+
if err != nil {
45+
logger.Error(err, "error getting target time")
46+
os.Exit(1)
47+
}
48+
logger.Info("Target time", "time", targetTime.String())
49+
},
50+
}
51+
52+
func setupLogger(cmd *cobra.Command) error {
53+
logLevel, err := cmd.Flags().GetString("log-level")
54+
if err != nil {
55+
return fmt.Errorf("error getting 'log-level' flag: %v\n", err)
56+
}
57+
logTimeEncoder, err := cmd.Flags().GetString("log-time-encoder")
58+
if err != nil {
59+
return fmt.Errorf("error getting 'log-time-encoder' flag: %v\n", err)
60+
}
61+
logDev, err := cmd.Flags().GetBool("log-dev")
62+
if err != nil {
63+
return fmt.Errorf("error getting 'log-dev' flag: %v\n", err)
64+
}
65+
log.SetupLogger(logLevel, logTimeEncoder, logDev)
66+
return nil
67+
}
68+
69+
func getTargetTime() (time.Time, error) {
70+
if targetTimeRaw == "" {
71+
return time.Now(), nil
72+
}
73+
return backup.ParseBackupDate(targetTimeRaw)
74+
}

cmd/backup/restore.go

+22-17
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,64 @@
11
package backup
22

33
import (
4+
"fmt"
45
"os"
5-
"time"
66

7-
"github.com/mariadb-operator/mariadb-operator/pkg/pitr"
7+
"github.com/mariadb-operator/mariadb-operator/pkg/backup"
88
"github.com/spf13/cobra"
9-
ctrl "sigs.k8s.io/controller-runtime"
109
)
1110

12-
var PitrCmd = &cobra.Command{
11+
var restoreCommand = &cobra.Command{
1312
Use: "restore",
1413
Short: "Restore.",
15-
Long: `Finds the backup file to restore taking into account the target recovery time.`,
14+
Long: `Finds the backup file to be restored in order to implement point in time recovery.`,
1615
Run: func(cmd *cobra.Command, args []string) {
16+
if err := setupLogger(cmd); err != nil {
17+
fmt.Printf("error setting up logger: %v\n", err)
18+
os.Exit(1)
19+
}
20+
logger.Info("Starting restore")
1721

18-
setupLog.Info("Starting PITR")
19-
targetRecoveryTime, err := time.Parse(time.RFC3339, targetRecoveryTimeRaw)
22+
targetTime, err := getTargetTime()
2023
if err != nil {
21-
setupLog.Error(err, "error parsing target recovery time")
24+
logger.Error(err, "error getting target time")
2225
os.Exit(1)
2326
}
24-
setupLog.Info("Target recovery time", "time", targetRecoveryTime.String())
27+
logger.Info("Target time", "time", targetTime.String())
2528

2629
backupFileNames, err := getBackupFileNames()
2730
if err != nil {
28-
setupLog.Error(err, "error reading backup files", "path", backupPath)
31+
logger.Error(err, "error reading backup files", "path", path)
2932
os.Exit(1)
3033
}
3134

32-
targetRecoveryFile, err := pitr.GetTargetRecoveryFile(backupFileNames, targetRecoveryTime, ctrl.Log.WithName("pitr"))
35+
backupTargetFile, err := backup.GetBackupTargetFile(backupFileNames, targetTime, logger.WithName("point-in-time-recovery"))
3336
if err != nil {
34-
setupLog.Error(err, "error reading getting target recovery file", "time", targetRecoveryTime)
37+
logger.Error(err, "error reading getting target recovery file")
3538
os.Exit(1)
3639
}
40+
backupTargetFilepath := fmt.Sprintf("%s/%s", path, backupTargetFile)
41+
logger.Info("Target file", "time", backupTargetFilepath)
3742

38-
if err := os.WriteFile(backupTargetPath, []byte(targetRecoveryFile), 0644); err != nil {
39-
setupLog.Error(err, "error writing target recovery file")
43+
if err := os.WriteFile(targetFilePath, []byte(backupTargetFilepath), 0644); err != nil {
44+
logger.Error(err, "error writing target file")
4045
os.Exit(1)
4146
}
4247
},
4348
}
4449

4550
func getBackupFileNames() ([]string, error) {
46-
entries, err := os.ReadDir(backupPath)
51+
entries, err := os.ReadDir(path)
4752
if err != nil {
4853
return nil, err
4954
}
5055
var fileNames []string
5156
for _, e := range entries {
5257
name := e.Name()
53-
if pitr.IsValidBackupFile(name) {
58+
if backup.IsValidBackupFile(name) {
5459
fileNames = append(fileNames, name)
5560
} else {
56-
setupLog.V(1).Info("ignoring file", "file", name)
61+
logger.V(1).Info("ignoring file", "file", name)
5762
}
5863
}
5964
return fileNames, nil

cmd/controller/main.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import (
2929
"time"
3030

3131
mariadbv1alpha1 "github.com/mariadb-operator/mariadb-operator/api/v1alpha1"
32-
pitrcmd "github.com/mariadb-operator/mariadb-operator/cmd/pitr"
32+
backupcmd "github.com/mariadb-operator/mariadb-operator/cmd/backup"
3333
"github.com/mariadb-operator/mariadb-operator/controller"
3434
"github.com/mariadb-operator/mariadb-operator/pkg/builder"
3535
condition "github.com/mariadb-operator/mariadb-operator/pkg/condition"
@@ -328,7 +328,7 @@ var rootCmd = &cobra.Command{
328328
func main() {
329329
rootCmd.AddCommand(certControllerCmd)
330330
rootCmd.AddCommand(webhookCmd)
331-
rootCmd.AddCommand(pitrcmd.PitrCmd)
331+
rootCmd.AddCommand(backupcmd.RootCmd)
332332

333333
cobra.CheckErr(rootCmd.Execute())
334334
}

cmd/enterprise/main.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import (
88
"time"
99

1010
mariadbv1alpha1 "github.com/mariadb-operator/mariadb-operator/api/v1alpha1"
11-
pitrcmd "github.com/mariadb-operator/mariadb-operator/cmd/pitr"
11+
backupcmd "github.com/mariadb-operator/mariadb-operator/cmd/backup"
1212
"github.com/mariadb-operator/mariadb-operator/controller"
1313
"github.com/mariadb-operator/mariadb-operator/pkg/builder"
1414
condition "github.com/mariadb-operator/mariadb-operator/pkg/condition"
@@ -358,7 +358,7 @@ var rootCmd = &cobra.Command{
358358
}
359359

360360
func main() {
361-
rootCmd.AddCommand(pitrcmd.PitrCmd)
361+
rootCmd.AddCommand(backupcmd.RootCmd)
362362

363363
cobra.CheckErr(rootCmd.Execute())
364364
}

controller/restore_controller_test.go

+8-2
Original file line numberDiff line numberDiff line change
@@ -131,10 +131,16 @@ var _ = Describe("Restore controller", func() {
131131
return true
132132
}, testTimeout, testInterval).Should(BeTrue())
133133

134-
By("Expecting Job to have PITR init container")
134+
By("Expecting Job to have mariadb-operator init container")
135135
Expect(job.Spec.Template.Spec.InitContainers).To(ContainElement(MatchFields(IgnoreExtras,
136136
Fields{
137-
"Name": Equal("point-in-time-recovery"),
137+
"Name": Equal("mariadb-operator"),
138+
})))
139+
140+
By("Expecting Job to have mariadb container")
141+
Expect(job.Spec.Template.Spec.Containers).To(ContainElement(MatchFields(IgnoreExtras,
142+
Fields{
143+
"Name": Equal("mariadb"),
138144
})))
139145

140146
By("Expecting restore to be complete eventually")

make/build.mk

+4
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,7 @@ docker-push-ent: ## Push the enterprise image.
3636
.PHONY: docker-load-ent
3737
docker-load-ent: ## Load the enterprise image in KIND.
3838
$(MAKE) docker-load IMG=$(IMG_ENT)
39+
40+
.PHONY: docker-dev-ent
41+
docker-dev-ent: docker-build-ent docker-load-ent ## Build and load enterprise image for local development.
42+

make/dev.mk

+7-8
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,12 @@ CERT_CONTROLLER_FLAGS ?= --log-dev --log-level=debug --log-time-encoder=iso8601
6969
cert-controller: lint ## Run a cert-controller from your host.
7070
go run cmd/controller/*.go cert-controller $(CERT_CONTROLLER_FLAGS)
7171

72-
PITR_FLAGS ?= --log-dev --log-level=debug --log-time-encoder=iso8601 --backup-path=backup --result-file-path=backup/0-point-in-time-recovery.txt --target-recovery-time=1970-01-01T00:00:00Z
72+
BACKUP_FLAGS ?= --log-dev --log-level=debug --log-time-encoder=iso8601 --path=backup --target-time=1970-01-01T00:00:00Z --target-file-path=backup/0-backup-target.txt
7373

74-
.PHONY: pitr
75-
pitr: lint ## Run PITR from your host.
76-
go run cmd/controller/*.go pitr $(PITR_FLAGS)
77-
78-
.PHONY: pitr-ent
79-
pitr-ent: lint ## Run PITR enterprise from your host.
80-
go run cmd/enterprise/*.go pitr $(PITR_FLAGS)
74+
.PHONY: backup
75+
backup: lint ## Run backup from your host.
76+
go run cmd/controller/*.go backup $(BACKUP_FLAGS)
8177

78+
.PHONY: backup-restore
79+
backup-restore: lint ## Run restore from your host.
80+
go run cmd/controller/*.go backup restore $(BACKUP_FLAGS)

0 commit comments

Comments
 (0)