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

wip #58

Closed
wants to merge 11 commits into from
8 changes: 6 additions & 2 deletions .wordlist-en-custom.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ AES
API's
APIs
ARMv
ATTACHER
AcolumnName
AdditionalPodAffinity
AdditionalPodAntiAffinity
Expand All @@ -20,7 +19,9 @@ Azurite
BDR
BackupConfiguration
BackupList
BackupMethod
BackupPhase
BackupSnapshotStatus
BackupSource
BackupSpec
BackupStatus
Expand Down Expand Up @@ -55,6 +56,7 @@ Cecchi
CertificatesConfiguration
CertificatesStatus
Certmanager
ClassName
ClientCASecret
ClientCertsCASecret
ClientReplicationSecret
Expand Down Expand Up @@ -337,6 +339,7 @@ ServiceAccountTemplate
ServiceMonitor
Silvela
Slonik
SnapshotOwnerReference
SnapshotType
Snapshotting
StatefulSets
Expand Down Expand Up @@ -366,12 +369,14 @@ Valerio
VirtualBox
VolumeSnapshot
VolumeSnapshotClass
VolumeSnapshotConfiguration
WAL
WAL's
WALBackupConfiguration
WALs
Wadle
WalBackupConfiguration
WalClassName
YXBw
YY
YYYY
Expand Down Expand Up @@ -986,7 +991,6 @@ volumeMode
volumeMounts
volumeSnapshot
volumesnapshot
volumesnapshotclass
wal
walSegmentSize
walStorage
Expand Down
53 changes: 53 additions & 0 deletions api/v1/backup_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ limitations under the License.
package v1

import (
volumesnapshot "github.com/kubernetes-csi/external-snapshotter/client/v6/apis/volumesnapshot/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

Expand All @@ -43,6 +45,20 @@ const (
BackupPhaseWalArchivingFailing = "walArchivingFailing"
)

// BackupMethod defines the way of executing the physical base backups of
// the selected PostgreSQL instance
type BackupMethod string

const (
// BackupMethodVolumeSnapshot means using the volume snapshot
// Kubernetes feature
BackupMethodVolumeSnapshot BackupMethod = "volumeSnapshot"

// BackupMethodBarmanObjectStore means using barman to backup the
// PostgreSQL cluster
BackupMethodBarmanObjectStore BackupMethod = "barmanObjectStore"
)

// BackupSpec defines the desired state of Backup
type BackupSpec struct {
// The cluster to backup
Expand All @@ -56,6 +72,18 @@ type BackupSpec struct {
// standby, if available.
// +kubebuilder:validation:Enum=primary;prefer-standby
Target BackupTarget `json:"target,omitempty"`

// The backup method to be used, possible options are `barmanObjectStore`
// and `volumeSnapshot`. Defaults to: `barmanObjectStore`.
// +kubebuilder:validation:Enum=barmanObjectStore;volumeSnapshot
// +kubebuilder:default:=barmanObjectStore
Method BackupMethod `json:"method,omitempty"`
}

// BackupSnapshotStatus the fields exclusive to the volumeSnapshot method backup
type BackupSnapshotStatus struct {
// The snapshot lists, populated if it is a snapshot type backup
Snapshots []string `json:"snapshots,omitempty"`
}

// BackupStatus defines the observed state of Backup
Expand Down Expand Up @@ -122,6 +150,12 @@ type BackupStatus struct {

// Information to identify the instance where the backup has been taken from
InstanceID *InstanceID `json:"instanceID,omitempty"`

// BackupSnapshotStatus the status of to the volumeSnapshot backup
BackupSnapshotStatus BackupSnapshotStatus `json:"snapshotBackupStatus,omitempty"`

// The backup method being used
Method BackupMethod `json:"method,omitempty"`
}

// InstanceID contains the information to identify an instance
Expand Down Expand Up @@ -185,6 +219,25 @@ func (backupStatus *BackupStatus) SetAsCompleted() {
backupStatus.Error = ""
}

// SetAsStarted marks a certain backup as started
func (backupStatus *BackupStatus) SetAsStarted(targetPod *corev1.Pod, method BackupMethod) {
backupStatus.Phase = BackupPhaseStarted
backupStatus.InstanceID = &InstanceID{
PodName: targetPod.Name,
ContainerID: targetPod.Status.ContainerStatuses[0].ContainerID,
}
backupStatus.Method = method
}

// SetSnapshotList sets the Snapshots field from a list of VolumeSnapshot
func (snapshotStatus *BackupSnapshotStatus) SetSnapshotList(snapshots []*volumesnapshot.VolumeSnapshot) {
snapshotNames := make([]string, len(snapshots))
for idx, volumeSnapshot := range snapshots {
snapshotNames[idx] = volumeSnapshot.Name
}
snapshotStatus.Snapshots = snapshotNames
}

// IsDone check if a backup is completed or still in progress
func (backupStatus *BackupStatus) IsDone() bool {
return backupStatus.Phase == BackupPhaseCompleted || backupStatus.Phase == BackupPhaseFailed
Expand Down
72 changes: 72 additions & 0 deletions api/v1/backup_types_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
Copyright The CloudNativePG Contributors

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 v1

import (
volumesnapshot "github.com/kubernetes-csi/external-snapshotter/client/v6/apis/volumesnapshot/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

var _ = Describe("BackupStatus structure", func() {
It("can be set as started", func() {
status := BackupStatus{}
pod := corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "cluster-example-1",
},
Status: corev1.PodStatus{
ContainerStatuses: []corev1.ContainerStatus{
{
ContainerID: "container-id",
},
},
},
}

status.SetAsStarted(&pod, BackupMethodBarmanObjectStore)
Expect(status.Phase).To(BeEquivalentTo(BackupPhaseStarted))
Expect(status.InstanceID).ToNot(BeNil())
Expect(status.InstanceID.PodName).To(Equal("cluster-example-1"))
Expect(status.InstanceID.ContainerID).To(Equal("container-id"))
Expect(status.IsDone()).To(BeFalse())
})

It("can be set to contain a snapshot list", func() {
status := BackupStatus{}
status.BackupSnapshotStatus.SetSnapshotList([]*volumesnapshot.VolumeSnapshot{
{
ObjectMeta: metav1.ObjectMeta{
Name: "cluster-example-snapshot-1",
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "cluster-example-snapshot-2",
},
},
})

Expect(status.BackupSnapshotStatus.Snapshots).To(HaveLen(2))
Expect(status.BackupSnapshotStatus.Snapshots).To(ConsistOf(
"cluster-example-snapshot-1",
"cluster-example-snapshot-2"))
})
})
69 changes: 68 additions & 1 deletion api/v1/cluster_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,37 @@ const (
PGBouncerPoolerUserName = "cnpg_pooler_pgbouncer"
)

// SnapshotOwnerReference defines the reference type for the owner of the snapshot.
// This specifies which owner the processed resources should relate to.
type SnapshotOwnerReference string

// Constants to represent the allowed types for SnapshotOwnerReference.
const (
// ShapshotOwnerReferenceNone indicates that the snapshot does not have any owner reference.
ShapshotOwnerReferenceNone SnapshotOwnerReference = "none"
// SnapshotOwnerReferenceBackup indicates that the snapshot is owned by the backup resource.
SnapshotOwnerReferenceBackup SnapshotOwnerReference = "backup"
// SnapshotOwnerReferenceCluster indicates that the snapshot is owned by the cluster resource.
SnapshotOwnerReferenceCluster SnapshotOwnerReference = "cluster"
)

// VolumeSnapshotConfiguration represents the configuration for the execution of snapshot backups.
type VolumeSnapshotConfiguration struct {
// Labels are key-value pairs that will be added to .metadata.labels snapshot resources.
Labels map[string]string `json:"labels,omitempty"`
// Annotations key-value pairs that will be added to .metadata.annotations snapshot resources.
Annotations map[string]string `json:"annotations,omitempty"`
// ClassName specifies the Snapshot Class to be used for PG_DATA PersistentVolumeClaim.
// It is the default class for the other types if no specific class is present
ClassName string `json:"className,omitempty"`
// WalClassName specifies the Snapshot Class to be used for the PG_WAL PersistentVolumeClaim.
WalClassName string `json:"walClassName,omitempty"`
// SnapshotOwnerReference indicates the type of owner reference the snapshot should have. .
// +kubebuilder:validation:Enum=none;cluster;backup
// +kubebuilder:default:=none
SnapshotOwnerReference SnapshotOwnerReference `json:"snapshotOwnerReference,omitempty"`
}

// ClusterSpec defines the desired state of Cluster
type ClusterSpec struct {
// Description of this PostgreSQL cluster
Expand Down Expand Up @@ -594,6 +625,38 @@ const (
ConditionClusterReady ClusterConditionType = "Ready"
)

// A Condition that can be used to communicate the Backup progress
var (
// BackupSucceededCondition is added to a backup
// when it was completed correctly
BackupSucceededCondition = &metav1.Condition{
Type: string(ConditionBackup),
Status: metav1.ConditionTrue,
Reason: string(ConditionReasonLastBackupSucceeded),
Message: "Backup was successful",
}

// BackupStartingCondition is added to a backup
// when it started
BackupStartingCondition = &metav1.Condition{
Type: string(ConditionBackup),
Status: metav1.ConditionFalse,
Reason: string(ConditionBackupStarted),
Message: "New Backup starting up",
}

// BuildClusterBackupFailedCondition builds
// ConditionReasonLastBackupFailed condition
BuildClusterBackupFailedCondition = func(err error) *metav1.Condition {
return &metav1.Condition{
Type: string(ConditionBackup),
Status: metav1.ConditionFalse,
Reason: string(ConditionReasonLastBackupFailed),
Message: err.Error(),
}
}
)

// ConditionStatus defines conditions of resources
type ConditionStatus string

Expand Down Expand Up @@ -1468,17 +1531,21 @@ type BarmanObjectStoreConfiguration struct {
}

// BackupConfiguration defines how the backup of the cluster are taken.
// Currently the only supported backup method is barmanObjectStore.
// The supported backup methods are BarmanObjectStore and VolumeSnapshot.
// For details and examples refer to the Backup and Recovery section of the
// documentation
type BackupConfiguration struct {
// VolumeSnapshot provides the configuration for the execution of volume snapshot backups.
VolumeSnapshot *VolumeSnapshotConfiguration `json:"volumeSnapshot,omitempty"`

// The configuration for the barman-cloud tool suite
BarmanObjectStore *BarmanObjectStoreConfiguration `json:"barmanObjectStore,omitempty"`

// RetentionPolicy is the retention policy to be used for backups
// and WALs (i.e. '60d'). The retention policy is expressed in the form
// of `XXu` where `XX` is a positive integer and `u` is in `[dwm]` -
// days, weeks, months.
// It's currently only applicable when using the BarmanObjectStore method.
// +kubebuilder:validation:Pattern=^[1-9][0-9]*[dwm]$
// +optional
RetentionPolicy string `json:"retentionPolicy,omitempty"`
Expand Down
7 changes: 7 additions & 0 deletions api/v1/scheduledbackup_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ type ScheduledBackupSpec struct {
// standby, if available.
// +kubebuilder:validation:Enum=primary;prefer-standby
Target BackupTarget `json:"target,omitempty"`

// The backup method to be used, possible options are `barmanObjectStore`
// and `volumeSnapshot`. Defaults to: `barmanObjectStore`.
// +kubebuilder:validation:Enum=barmanObjectStore;volumeSnapshot
// +kubebuilder:default:=barmanObjectStore
Method BackupMethod `json:"method,omitempty"`
}

// ScheduledBackupStatus defines the observed state of ScheduledBackup
Expand Down Expand Up @@ -152,6 +158,7 @@ func (scheduledBackup *ScheduledBackup) CreateBackup(name string) *Backup {
Spec: BackupSpec{
Cluster: scheduledBackup.Spec.Cluster,
Target: scheduledBackup.Spec.Target,
Method: scheduledBackup.Spec.Method,
},
}
utils.InheritAnnotations(&backup.ObjectMeta, scheduledBackup.Annotations, nil, configuration.Current)
Expand Down
Loading
Loading