Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Nebula scheduled backup CRD #416

Merged
merged 11 commits into from
Jan 27, 2024
45 changes: 34 additions & 11 deletions apis/apps/v1alpha1/backupschedule_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,30 +20,51 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// BackupConditionType represents a valid condition of a Backup.
type ScheduledBackupConditionType string

const (
// ScheduledBackupPending means the scheduled backup job is pending, waiting for creation of the backup cronjob
ScheduledBackupPending ScheduledBackupConditionType = "Pending"
// ScheduledBackupScheduled means the scheduled backup cronjob was created successfully and no active backup jobs are running
// if there was an active backup job, the job has executed successfully and the backup data has been loaded into the nebula cluster.
ScheduledBackupScheduled ScheduledBackupConditionType = "Scheduled"
// ScheduledBackupRunning means there's an active backup job current running.
ScheduledBackupRunning ScheduledBackupConditionType = "Running"
// ScheduledBackupPaused means the schedule backup is currently suspended
ScheduledBackupPaused ScheduledBackupConditionType = "Paused"
// ScheduledBackupJobFailed means the active backup job has failed to execute successfully
ScheduledBackupJobFailed ScheduledBackupConditionType = "Backup job failed"
// BackupFailed means the backup cron job creation has failed.
ScheduledBackupFailed ScheduledBackupConditionType = "Cron Creation Failed"
kevinliu24 marked this conversation as resolved.
Show resolved Hide resolved
// BackupInvalid means invalid backup CR.
ScheduledBackupInvalid ScheduledBackupConditionType = "Invalid"
)

// +genclient
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:resource:shortName="bs"

type BackupSchedule struct {
type NebulaScheduledBackup struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Spec BackupScheduleSpec `json:"spec,omitempty"`
Status BackupScheduleStatus `json:"status,omitempty"`
Spec ScheduledBackupSpec `json:"spec,omitempty"`
Status ScheduledBackupStatus `json:"status,omitempty"`
}

// +kubebuilder:object:root=true
// BackupScheduleList contains a list of BackupSchedule.
type BackupScheduleList struct {
// NebulaScheduledBackupList contains a list of NebulaScheduledBackup.
type NebulaScheduledBackupList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`

Items []BackupSchedule `json:"items"`
Items []NebulaScheduledBackup `json:"items"`
}

// BackupScheduleSpec contains the specification for a backupSchedule of a nebula cluster backupSchedule.
type BackupScheduleSpec struct {
// ScheduledBackupSpec contains the specification for a NebulaScheduledBackup of a nebula cluster NebulaScheduledBackup.
type ScheduledBackupSpec struct {
// Schedule specifies the cron string used for backup scheduling.
Schedule string `json:"schedule"`
// Pause means paused backupSchedule
kevinliu24 marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -60,14 +81,16 @@ type BackupScheduleSpec struct {
// LogBackupTemplate is the specification of the log backup structure to get scheduled.
}

// BackupScheduleStatus represents the current status of a nebula cluster backupSchedule.
type BackupScheduleStatus struct {
// ScheduledBackupStatus represents the current status of a nebula cluster NebulaScheduledBackup.
type ScheduledBackupStatus struct {
// LastBackup represents the last backup.
LastBackup string `json:"lastBackup,omitempty"`
// LastBackupTime represents the last time the backup was successfully created.
LastBackupTime *metav1.Time `json:"lastBackupTime,omitempty"`
// Phase represents the status of the scheduled backup
Phase ScheduledBackupConditionType `json:"phase,omitempty"`
}

func init() {
SchemeBuilder.Register(&BackupSchedule{}, &BackupScheduleList{})
SchemeBuilder.Register(&NebulaScheduledBackup{}, &NebulaScheduledBackupList{})
}
38 changes: 19 additions & 19 deletions apis/apps/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 29 additions & 7 deletions config/crd/bases/apps.nebula-graph.io_backupschedules.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,39 @@ metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.11.3
creationTimestamp: null
name: backupschedules.apps.nebula-graph.io
name: nebulascheduledbackup.apps.nebula-graph.io
spec:
group: apps.nebula-graph.io
names:
kind: BackupSchedule
listKind: BackupScheduleList
plural: backupschedules
kind: NebulaScheduledBackup
listKind: NebulaScheduledBackupList
plural: nebulascheduledbackups
shortNames:
- bs
singular: backupschedule
- nsb
singular: nebulascheduledbackup
scope: Namespaced
versions:
- name: v1alpha1
- additionalPrinterColumns:
- description: The current schedule set for the scheduled backup
jsonPath: .properties.schedule
name: Schedule
type: string
- description: The current status of the scheduled backup
jsonPath: .status.phase
name: Status
type: string
- description: The name of the last backup ran
jsonPath: .status.lastBackup
name: Last Backup Name
type: string
- description: The timestamp at which the last backup was ran
jsonPath: .status.timeCompleted
name: Last Backup Time
type: date
- jsonPath: .metadata.creationTimestamp
name: Age
type: date
name: v1alpha1
schema:
openAPIV3Schema:
properties:
Expand Down Expand Up @@ -94,6 +114,8 @@ spec:
lastBackupTime:
format: date-time
type: string
phase:
type: string
type: object
type: object
served: true
Expand Down
10 changes: 10 additions & 0 deletions config/rbac/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,16 @@ rules:
- patch
- update
- watch
- apiGroups:
- ""
resources:
- jobs
verbs:
- create
- get
- list
- watch
- delete
- apiGroups:
- apps.nebula-graph.io
resources:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
Copyright 2023 Vesoft Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package nebulascheduledbackup

import (
"k8s.io/klog/v2"

"github.com/vesoft-inc/nebula-operator/apis/apps/v1alpha1"
"github.com/vesoft-inc/nebula-operator/pkg/kube"
"github.com/vesoft-inc/nebula-operator/pkg/util/errors"
)

type ControlInterface interface {
SyncNebulaScheduledBackup(bp *v1alpha1.NebulaScheduledBackup) error
}

var _ ControlInterface = (*defaultScheduledBackupControl)(nil)

type defaultScheduledBackupControl struct {
clientSet kube.ClientSet
scheduledBackupManager Manager
}

func NewBackupControl(clientSet kube.ClientSet, scheduledBackupManager Manager) ControlInterface {
return &defaultScheduledBackupControl{
clientSet: clientSet,
scheduledBackupManager: scheduledBackupManager,
}
}

func (c *defaultScheduledBackupControl) SyncNebulaScheduledBackup(sbp *v1alpha1.NebulaScheduledBackup) error {
kevinliu24 marked this conversation as resolved.
Show resolved Hide resolved
phase := sbp.Status.Phase
if phase == "" {
phase = v1alpha1.ScheduledBackupPending
}

switch phase {
case v1alpha1.ScheduledBackupPending:
klog.Infof("creating scheduled backup job %s", sbp.Name)
err := c.scheduledBackupManager.Create(sbp)
if err != nil && !errors.IsReconcileError(err) {
klog.Errorf("Fail to create NebulaScheduledBackup [%s/%s], %v", sbp.Namespace, sbp.Name, err)
if err = c.clientSet.NebulaScheduledBackup().UpdateNebulaScheduledBackupStatus(sbp, &kube.ScheduledBackupUpdateStatus{
Phase: v1alpha1.ScheduledBackupScheduled,
}); err != nil {
klog.Errorf("Fail to update the condition of NebulaScheduledBackup [%s/%s], %v", sbp.Namespace, sbp.Name, err)
}
}
return err
default:
if sbp.Spec.Pause && phase == v1alpha1.ScheduledBackupPaused {
break
}
klog.Infof("sync backup job %s", sbp.Name)
err := c.scheduledBackupManager.Sync(sbp)
if err != nil && !errors.IsReconcileError(err) {
klog.Errorf("Fail to sync NebulaScheduledBackup [%s/%s], %v", sbp.Namespace, sbp.Name, err)
if err = c.clientSet.NebulaScheduledBackup().UpdateNebulaScheduledBackupStatus(sbp, &kube.ScheduledBackupUpdateStatus{
Phase: v1alpha1.ScheduledBackupFailed,
}); err != nil {
klog.Errorf("Fail to update the condition of NebulaScheduledBackup [%s/%s], %v", sbp.Namespace, sbp.Name, err)
}
}
return err
}

klog.Infof("sync NebulaScheduledBackup success, scheduled backup %s phase is %s", sbp.Name, phase)
return nil
}
Loading