package factory import ( "errors" polardbxv1 "github.com/alibaba/polardbx-operator/api/v1" polardbxv1polardbx "github.com/alibaba/polardbx-operator/api/v1/polardbx" "github.com/alibaba/polardbx-operator/pkg/operator/v1/polardbx/convention" "github.com/alibaba/polardbx-operator/pkg/operator/v1/polardbx/meta" "github.com/alibaba/polardbx-operator/pkg/util/name" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" ) type PolarDBXClusterMetadata struct { // Name records name of original pxc Name string `json:"name,omitempty"` // UID records uid of original pxc UID types.UID `json:"uid,omitempty"` // Spec records the topology from original pxc Spec *polardbxv1.PolarDBXClusterSpec `json:"spec,omitempty"` // Secrets records account and password for pxc Secrets []polardbxv1polardbx.PrivilegeItem `json:"secrets,omitempty"` } type XstoreMetadata struct { // Name records name of original xstore Name string `json:"name,omitempty"` // UID records uid of original xstore UID types.UID `json:"uid,omitempty"` // BackupName records name of xstore backup of original xstore BackupName string `json:"backupName,omitempty"` // LastCommitIndex records the last binlog index during full backup LastCommitIndex int64 `json:"lastCommitIndex,omitempty"` // Secrets records account and password for xstore Secrets []polardbxv1polardbx.PrivilegeItem `json:"secrets,omitempty"` } // MetadataBackup defines metadata to be uploaded during backup type MetadataBackup struct { // PolarDBXClusterMetadata records metadata of pxc which backed up PolarDBXClusterMetadata PolarDBXClusterMetadata `json:"polarDBXClusterMetadata,omitempty"` // XstoreMetadataList records metadata of each xstore which backed up XstoreMetadataList []XstoreMetadata `json:"xstoreMetadataList,omitempty"` // BackupSetName records name of pxb BackupSetName string `json:"backupSetName,omitempty"` // BackupRootPath records the root path for pxb BackupRootPath string `json:"backupRootPath,omitempty"` // StartTime records start time of backup StartTime *metav1.Time `json:"startTime,omitempty"` // EndTime records end time of backup EndTime *metav1.Time `json:"endTime,omitempty"` // LatestRecoverableTimestamp records the latest timestamp that can recover from current backup set LatestRecoverableTimestamp *metav1.Time `json:"latestRecoverableTimestamp,omitempty"` } func (m *MetadataBackup) GetXstoreNameList() []string { xstoreNameList := make([]string, len(m.XstoreMetadataList)) for i, xstoreMetadata := range m.XstoreMetadataList { xstoreNameList[i] = xstoreMetadata.Name } return xstoreNameList } func (m *MetadataBackup) GetXstoreMetadataByName(xstoreName string) (*XstoreMetadata, error) { for i := range m.XstoreMetadataList { if m.XstoreMetadataList[i].Name == xstoreName { return &m.XstoreMetadataList[i], nil } } return nil, errors.New("no such metadata related to xstore " + xstoreName) } func (f *objectFactory) NewPolarDBXBackupBySchedule() (*polardbxv1.PolarDBXBackup, error) { backupSchedule := f.rc.MustGetPolarDBXBackupSchedule() backupName := name.NewSplicedName( name.WithTokens(backupSchedule.Spec.BackupSpec.Cluster.Name, "backup", backupSchedule.Status.NextBackupTime.Format("200601021504")), name.WithPrefix("scheduled-backup"), ) backup := &polardbxv1.PolarDBXBackup{ ObjectMeta: metav1.ObjectMeta{ Namespace: backupSchedule.Namespace, Name: backupName, Labels: map[string]string{ meta.LabelBackupSchedule: backupSchedule.Name, }, }, Spec: *backupSchedule.Spec.BackupSpec.DeepCopy(), } return backup, nil } func (f *objectFactory) NewXStoreBackup( xstore *polardbxv1.XStore) (*polardbxv1.XStoreBackup, error) { backup := f.rc.MustGetPolarDBXBackup() xstoreBackup := &polardbxv1.XStoreBackup{ ObjectMeta: metav1.ObjectMeta{ Namespace: backup.Namespace, Name: name.NewSplicedName( name.WithTokens(backup.Name, xstore.Name), name.WithPrefix("xstore-backup"), ), Labels: map[string]string{ meta.LabelName: backup.Spec.Cluster.Name, meta.LabelTopBackup: backup.Name, meta.LabelBackupXStore: xstore.Name, meta.LabelBackupXStoreUID: string(xstore.UID), }, }, Spec: polardbxv1.XStoreBackupSpec{ XStore: polardbxv1.XStoreReference{ Name: xstore.Name, UID: xstore.UID, }, RetentionTime: backup.Spec.RetentionTime, StorageProvider: backup.Spec.StorageProvider, Engine: xstore.Spec.Engine, PreferredBackupRole: backup.Spec.PreferredBackupRole, }, } return xstoreBackup, nil } func (f *objectFactory) newDummyAnnotation() map[string]string { return map[string]string{ meta.AnnotationDummyBackup: "true", } } func (f *objectFactory) NewDummyPolarDBXBackup(metadata *MetadataBackup) (*polardbxv1.PolarDBXBackup, error) { if metadata == nil { return nil, errors.New("not enough information to create dummy polardbx backup") } polardbx := f.rc.MustGetPolarDBX() polardbxBackup := &polardbxv1.PolarDBXBackup{ ObjectMeta: metav1.ObjectMeta{ Name: name.NewSplicedName( name.WithTokens(metadata.BackupSetName, "dummy"), name.WithPrefix("dummy-backup"), ), Namespace: polardbx.Namespace, Annotations: f.newDummyAnnotation(), }, Spec: polardbxv1.PolarDBXBackupSpec{ Cluster: polardbxv1.PolarDBXClusterReference{ Name: metadata.PolarDBXClusterMetadata.Name, UID: metadata.PolarDBXClusterMetadata.UID, }, StorageProvider: *polardbx.Spec.Restore.StorageProvider, }, Status: polardbxv1.PolarDBXBackupStatus{ Phase: polardbxv1.BackupDummy, BackupRootPath: polardbx.Spec.Restore.From.BackupSetPath, ClusterSpecSnapshot: metadata.PolarDBXClusterMetadata.Spec, XStores: metadata.GetXstoreNameList(), Backups: make(map[string]string), }, } return polardbxBackup, nil } func (f *objectFactory) NewDummyXstoreBackup(xstoreName string, polardbxBackup *polardbxv1.PolarDBXBackup, metadata *MetadataBackup) (*polardbxv1.XStoreBackup, error) { if metadata == nil { return nil, errors.New("not enough information to create dummy xstore backup") } xstoreMetadata, err := metadata.GetXstoreMetadataByName(xstoreName) if err != nil { return nil, err } xstoreBackup := &polardbxv1.XStoreBackup{ ObjectMeta: metav1.ObjectMeta{ Name: name.NewSplicedName( name.WithTokens(polardbxBackup.Name, xstoreName), name.WithPrefix("dummy-xstore-backup"), ), Namespace: polardbxBackup.Namespace, Annotations: f.newDummyAnnotation(), }, Spec: polardbxv1.XStoreBackupSpec{ XStore: polardbxv1.XStoreReference{ Name: xstoreName, UID: xstoreMetadata.UID, }, StorageProvider: polardbxBackup.Spec.StorageProvider, }, Status: polardbxv1.XStoreBackupStatus{ Phase: polardbxv1.XStoreBackupDummy, CommitIndex: xstoreMetadata.LastCommitIndex, BackupRootPath: metadata.BackupRootPath, }, } return xstoreBackup, nil } func (f *objectFactory) NewDummySecretBackup(sourceSecretName string, metadata *MetadataBackup) (*corev1.Secret, error) { polardbx := f.rc.MustGetPolarDBX() var dummySecretName string var sourceSecrets *[]polardbxv1polardbx.PrivilegeItem accounts := make(map[string]string) if sourceSecretName == metadata.PolarDBXClusterMetadata.Name { // secret of cn dummySecretName = name.NewSplicedName( name.WithTokens(metadata.BackupSetName, "dummy"), name.WithPrefix("dummy-secret"), ) sourceSecrets = &metadata.PolarDBXClusterMetadata.Secrets } else { // secret of dn dummySecretName = name.NewSplicedName( name.WithTokens(metadata.BackupSetName, "dummy", sourceSecretName), name.WithPrefix("dummy-xstore-secret"), ) xstoreMetadata, err := metadata.GetXstoreMetadataByName(sourceSecretName) if err != nil { return nil, err } sourceSecrets = &xstoreMetadata.Secrets } for _, item := range *sourceSecrets { accounts[item.Username] = item.Password } return &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: dummySecretName, Namespace: polardbx.Namespace, Labels: convention.ConstLabels(polardbx), }, StringData: accounts, }, nil }