Skip to content

Commit 2e3476d

Browse files
committed
*: Support make S3 and NFS backup schedule together #689
1 parent fa20056 commit 2e3476d

File tree

6 files changed

+107
-17
lines changed

6 files changed

+107
-17
lines changed

api/v1alpha1/mysqlcluster_types.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,10 @@ type MysqlClusterSpec struct {
9292
// +optional
9393
BackupSchedule string `json:"backupSchedule,omitempty"`
9494

95+
// Specify that crontab job backup both on NFS and S3 storage.
96+
// +optional
97+
BothS3NFS *BothS3NFSOpt `json:"bothS3NFS,omitempty"`
98+
9599
// If set keeps last BackupScheduleJobsHistoryLimit Backups
96100
// +optional
97101
// +kubebuilder:default:=6
@@ -288,6 +292,13 @@ type Persistence struct {
288292
Size string `json:"size,omitempty"`
289293
}
290294

295+
// bothS3NFS opt
296+
type BothS3NFSOpt struct {
297+
// NFS schedule.
298+
NFSSchedule string `json:"nfsSchedule,omitempty"`
299+
S3Schedule string `json:"s3Schedule,omitempty"`
300+
}
301+
291302
// ClusterState defines cluster state.
292303
type ClusterState string
293304

api/v1alpha1/mysqlcluster_webhook.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ func (r *MysqlCluster) ValidateCreate() error {
5858
if err := r.validateNFSServerAddress(r); err != nil {
5959
return err
6060
}
61+
62+
if err := r.validBothS3NFS(); err != nil {
63+
return err
64+
}
65+
6166
if err := r.validateMysqlVersionAndImage(); err != nil {
6267
return err
6368
}
@@ -85,6 +90,11 @@ func (r *MysqlCluster) ValidateUpdate(old runtime.Object) error {
8590
if err := r.validateLowTableCase(oldCluster); err != nil {
8691
return err
8792
}
93+
94+
if err := r.validBothS3NFS(); err != nil {
95+
return err
96+
}
97+
8898
if err := r.validateMysqlVersionAndImage(); err != nil {
8999
return err
90100
}
@@ -210,3 +220,13 @@ func (r *MysqlCluster) validateMysqlVersion() error {
210220
}
211221
return nil
212222
}
223+
224+
// Validate BothS3NFS
225+
func (r *MysqlCluster) validBothS3NFS() error {
226+
if r.Spec.BothS3NFS != nil &&
227+
(len(r.Spec.NFSServerAddress) == 0 ||
228+
len(r.Spec.BackupSecretName) == 0) {
229+
return apierrors.NewForbidden(schema.GroupResource{}, "", fmt.Errorf("if BothS3NFS is set, backupSchedule/backupSecret/nfsAddress should not empty"))
230+
}
231+
return nil
232+
}

api/v1alpha1/zz_generated.deepcopy.go

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

backup/cronbackup.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ type CronJob struct {
2424
BackupScheduleJobsHistoryLimit *int
2525
Image string
2626
NFSServerAddress string
27-
Log logr.Logger
27+
BackupType string
28+
29+
Log logr.Logger
2830
}
2931

3032
func (j *CronJob) Run() {
@@ -45,7 +47,7 @@ func (j *CronJob) Run() {
4547
log.Info("at least a backup is running", "running_backups_count", j.scheduledBackupsRunningCount())
4648
return
4749
}
48-
50+
//TODO: if BothS3NFS, it need create backup without nfs address.
4951
// create the backup
5052
if _, err := j.createBackup(); err != nil {
5153
log.Error(err, "failed to create backup")
@@ -118,7 +120,7 @@ func (j *CronJob) backupGC() {
118120
}
119121

120122
func (j *CronJob) createBackup() (*apiv1alpha1.Backup, error) {
121-
backupName := fmt.Sprintf("%s-auto-%s", j.ClusterName, time.Now().Format("2006-01-02t15-04-05"))
123+
backupName := fmt.Sprintf("%s-%s-%s", j.ClusterName, j.BackupType, time.Now().Format("2006-01-02t15-04-05"))
122124

123125
backup := &apiv1alpha1.Backup{
124126
ObjectMeta: metav1.ObjectMeta{

config/crd/bases/mysql.radondb.com_mysqlclusters.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,15 @@ spec:
7070
description: Represents the name of the secret that contains credentials
7171
to connect to the storage provider to store backups.
7272
type: string
73+
bothS3NFS:
74+
description: Specify that crontab job backup both on NFS and S3 storage.
75+
properties:
76+
nfsSchedule:
77+
description: NFS schedule.
78+
type: string
79+
s3Schedule:
80+
type: string
81+
type: object
7382
metricsOpts:
7483
default:
7584
enabled: false

controllers/backupcron_controller.go

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -90,39 +90,64 @@ func (r *BackupCronReconciler) Reconcile(ctx context.Context, req ctrl.Request)
9090
return ctrl.Result{}, err
9191
}
9292
// if spec.backupScheduler is not set then don't do anything
93-
if len(instance.Spec.BackupSchedule) == 0 || *instance.Spec.Replicas == 0 {
93+
if instance.Spec.BothS3NFS == nil &&
94+
(len(instance.Spec.BackupSchedule) == 0 || *instance.Spec.Replicas == 0) {
9495
if err := r.Cron.Remove(instance.Name); err == nil {
9596
log.V(1).Info("remove cronjob from cluster", "name", instance.Name)
9697
}
9798

9899
return reconcile.Result{}, nil
99100
}
101+
// do the bothS3NFS
102+
if instance.Spec.BothS3NFS != nil {
103+
froms := []struct {
104+
Sche string
105+
T string
106+
}{
107+
{instance.Spec.BothS3NFS.NFSSchedule, "nfs"},
108+
{instance.Spec.BothS3NFS.S3Schedule, "s3"},
109+
}
100110

101-
schedule, err := cron.Parse(instance.Spec.BackupSchedule)
102-
if err != nil {
103-
return reconcile.Result{}, fmt.Errorf("failed to parse schedule: %s", err)
104-
}
111+
for _, f := range froms {
112+
schestr, t := f.Sche, f.T
113+
schedule, err := cron.Parse(schestr)
114+
if err != nil {
115+
return reconcile.Result{}, fmt.Errorf("failed to parse schedule: %s", err)
116+
}
117+
if err := r.updateClusterSchedule(ctx, instance.Unwrap(), schedule, t, log); err != nil {
118+
return ctrl.Result{}, err
119+
}
120+
}
121+
return ctrl.Result{}, nil
122+
} else {
123+
schedule, err := cron.Parse(instance.Spec.BackupSchedule)
124+
if err != nil {
125+
return reconcile.Result{}, fmt.Errorf("failed to parse schedule: %s", err)
126+
}
127+
128+
log.V(1).Info("register cluster in cronjob", "key", instance, "schedule", schedule)
105129

106-
log.V(1).Info("register cluster in cronjob", "key", instance, "schedule", schedule)
130+
return ctrl.Result{}, r.updateClusterSchedule(ctx, instance.Unwrap(), schedule, "", log)
131+
}
107132

108-
return ctrl.Result{}, r.updateClusterSchedule(ctx, instance.Unwrap(), schedule, log)
109133
}
110134

111135
// updateClusterSchedule creates/updates a cron job for specified cluster.
112-
func (r *BackupCronReconciler) updateClusterSchedule(ctx context.Context, cluster *apiv1alpha1.MysqlCluster, schedule cron.Schedule, log logr.Logger) error {
136+
func (r *BackupCronReconciler) updateClusterSchedule(ctx context.Context, cluster *apiv1alpha1.MysqlCluster, schedule cron.Schedule, BackupType string, log logr.Logger) error {
113137

114138
r.LockJobRegister.Lock()
115139
defer r.LockJobRegister.Unlock()
116140

117141
for _, entry := range r.Cron.Entries() {
118142
j, ok := entry.Job.(*backup.CronJob)
119-
if ok && j.ClusterName == cluster.Name && j.Namespace == cluster.Namespace {
143+
if ok && j.ClusterName == cluster.Name &&
144+
j.Namespace == cluster.Namespace && j.BackupType == BackupType {
120145
log.V(1).Info("cluster already added to cron.", "key", cluster)
121146

122147
// change scheduler for already added crons
123148
if !reflect.DeepEqual(entry.Schedule, schedule) {
124149
log.Info("update cluster scheduler", "key", cluster,
125-
"scheduler", cluster.Spec.BackupSchedule)
150+
"scheduler", schedule)
126151

127152
if err := r.Cron.Remove(cluster.Name); err != nil {
128153
return err
@@ -136,17 +161,20 @@ func (r *BackupCronReconciler) updateClusterSchedule(ctx context.Context, cluste
136161
return nil
137162
}
138163
}
164+
nfsServerAddress := ""
165+
if BackupType == "nfs" {
166+
nfsServerAddress = cluster.Spec.NFSServerAddress
167+
}
139168

140169
r.Cron.Schedule(schedule, &backup.CronJob{
141170
ClusterName: cluster.Name,
142171
Namespace: cluster.Namespace,
143172
Client: r.Client,
144173
Image: cluster.Spec.PodPolicy.SidecarImage,
145174
BackupScheduleJobsHistoryLimit: cluster.Spec.BackupScheduleJobsHistoryLimit,
146-
//BackupRemoteDeletePolicy: cluster.Spec.BackupRemoteDeletePolicy,
147-
148-
NFSServerAddress: cluster.Spec.NFSServerAddress,
149-
Log: log,
175+
NFSServerAddress: nfsServerAddress,
176+
BackupType: BackupType,
177+
Log: log,
150178
}, cluster.Name)
151179

152180
return nil

0 commit comments

Comments
 (0)