mirror of
https://github.com/cloudnative-pg/plugin-barman-cloud.git
synced 2026-01-11 21:23:12 +01:00
feat(spike): backup method
Signed-off-by: Armando Ruocco <armando.ruocco@enterprisedb.com>
This commit is contained in:
parent
dd6548c4a2
commit
57160bb6bf
@ -62,12 +62,13 @@ func main() {
|
||||
}
|
||||
|
||||
if err := mgr.Add(&instance.CNPGI{
|
||||
Client: mgr.GetClient(),
|
||||
Client: mgr.GetClient(),
|
||||
Recorder: mgr.GetEventRecorderFor("cnpg-i"),
|
||||
ClusterObjectKey: client.ObjectKey{
|
||||
Namespace: namespace,
|
||||
Name: clusterName,
|
||||
},
|
||||
BarmanObjectKey: client.ObjectKey{
|
||||
WALConfigurationKey: client.ObjectKey{
|
||||
Namespace: namespace,
|
||||
Name: boName,
|
||||
},
|
||||
|
||||
12
go.mod
12
go.mod
@ -4,9 +4,9 @@ go 1.22.0
|
||||
|
||||
require (
|
||||
github.com/cloudnative-pg/barman-cloud v0.0.0-20240924124724-92831d48562a
|
||||
github.com/cloudnative-pg/cloudnative-pg v1.24.0
|
||||
github.com/cloudnative-pg/cloudnative-pg v1.24.1-0.20241001084914-829808376542
|
||||
github.com/cloudnative-pg/cnpg-i v0.0.0-20240924030516-c5636170f248
|
||||
github.com/cloudnative-pg/cnpg-i-machinery v0.0.0-20240926153929-09e2c6f6689b
|
||||
github.com/cloudnative-pg/cnpg-i-machinery v0.0.0-20241001135556-db88a95a39eb
|
||||
github.com/cloudnative-pg/machinery v0.0.0-20241001075747-34c8797af80f
|
||||
github.com/onsi/ginkgo/v2 v2.20.2
|
||||
github.com/onsi/gomega v1.34.2
|
||||
@ -114,12 +114,12 @@ require (
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
k8s.io/apiextensions-apiserver v0.31.0 // indirect
|
||||
k8s.io/apiserver v0.31.0 // indirect
|
||||
k8s.io/component-base v0.31.0 // indirect
|
||||
k8s.io/apiextensions-apiserver v0.31.1 // indirect
|
||||
k8s.io/apiserver v0.31.1 // indirect
|
||||
k8s.io/component-base v0.31.1 // indirect
|
||||
k8s.io/klog/v2 v2.130.1 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20240903163716-9e1beecbcb38 // indirect
|
||||
k8s.io/utils v0.0.0-20240902221715-702e33fdd3c3 // indirect
|
||||
k8s.io/utils v0.0.0-20240921022957-49e7df575cb6 // indirect
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
|
||||
|
||||
24
go.sum
24
go.sum
@ -16,12 +16,12 @@ github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UF
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cloudnative-pg/barman-cloud v0.0.0-20240924124724-92831d48562a h1:0v1ML9Eibfq3helbT9GtU0EstqFtG91k/MPO9azY5ME=
|
||||
github.com/cloudnative-pg/barman-cloud v0.0.0-20240924124724-92831d48562a/go.mod h1:Jm0tOp5oB7utpt8wz6RfSv31h1mThOtffjfyxVupriE=
|
||||
github.com/cloudnative-pg/cloudnative-pg v1.24.0 h1:lY9IP/Gnh5ogNcFGoPnbD2eOiHdSdbdEp0PaUdOAMDQ=
|
||||
github.com/cloudnative-pg/cloudnative-pg v1.24.0/go.mod h1:n7Qqax6os+x3+7Qu/GojUUeKlL1ELGV63dcO/tzIfB4=
|
||||
github.com/cloudnative-pg/cloudnative-pg v1.24.1-0.20241001084914-829808376542 h1:IXf5lj+m4CBqzckQ9L/9hJ01JUoVw5N0FuPex0sVdVo=
|
||||
github.com/cloudnative-pg/cloudnative-pg v1.24.1-0.20241001084914-829808376542/go.mod h1:L8M+kTGpz/eaLZj46+4sARvO/vDYlo/m1xOigI/ghBA=
|
||||
github.com/cloudnative-pg/cnpg-i v0.0.0-20240924030516-c5636170f248 h1:eUGzb7YNjVLilwhgZoe4hDOO70fci3oqb/ZzQFbN3xg=
|
||||
github.com/cloudnative-pg/cnpg-i v0.0.0-20240924030516-c5636170f248/go.mod h1:K9/4eAT3rh2bKIWyujoN8BIPRXa4d1Ls+eBY8PE8y6w=
|
||||
github.com/cloudnative-pg/cnpg-i-machinery v0.0.0-20240926153929-09e2c6f6689b h1:T9G61tzOBoB5yvlDPULUoiUl6QxPmti3pkNFhQYGGQY=
|
||||
github.com/cloudnative-pg/cnpg-i-machinery v0.0.0-20240926153929-09e2c6f6689b/go.mod h1:dV1+nE7jWENm/fcnKBeKsaScMz685rQPbPCCDydJgsY=
|
||||
github.com/cloudnative-pg/cnpg-i-machinery v0.0.0-20241001135556-db88a95a39eb h1:fDZ4mOSwgEUKaXJI3a37Bw0bPa8bl3DqZ9nPu/6CiJ4=
|
||||
github.com/cloudnative-pg/cnpg-i-machinery v0.0.0-20241001135556-db88a95a39eb/go.mod h1:mHEVy/Guae+rij1qlgwHg+lyFKDX48qjTL4lAqE7OJs=
|
||||
github.com/cloudnative-pg/machinery v0.0.0-20241001075747-34c8797af80f h1:RgPmQJkuSu3eTdfd4T2K95RYQi57LHB2+Jfsu/faKOM=
|
||||
github.com/cloudnative-pg/machinery v0.0.0-20241001075747-34c8797af80f/go.mod h1:bWp1Es5zlxElg4Z/c5f0RKOkDcyNvDHdYIvNcPQU4WM=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
@ -286,22 +286,22 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
k8s.io/api v0.31.1 h1:Xe1hX/fPW3PXYYv8BlozYqw63ytA92snr96zMW9gWTU=
|
||||
k8s.io/api v0.31.1/go.mod h1:sbN1g6eY6XVLeqNsZGLnI5FwVseTrZX7Fv3O26rhAaI=
|
||||
k8s.io/apiextensions-apiserver v0.31.0 h1:fZgCVhGwsclj3qCw1buVXCV6khjRzKC5eCFt24kyLSk=
|
||||
k8s.io/apiextensions-apiserver v0.31.0/go.mod h1:b9aMDEYaEe5sdK+1T0KU78ApR/5ZVp4i56VacZYEHxk=
|
||||
k8s.io/apiextensions-apiserver v0.31.1 h1:L+hwULvXx+nvTYX/MKM3kKMZyei+UiSXQWciX/N6E40=
|
||||
k8s.io/apiextensions-apiserver v0.31.1/go.mod h1:tWMPR3sgW+jsl2xm9v7lAyRF1rYEK71i9G5dRtkknoQ=
|
||||
k8s.io/apimachinery v0.31.1 h1:mhcUBbj7KUjaVhyXILglcVjuS4nYXiwC+KKFBgIVy7U=
|
||||
k8s.io/apimachinery v0.31.1/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo=
|
||||
k8s.io/apiserver v0.31.0 h1:p+2dgJjy+bk+B1Csz+mc2wl5gHwvNkC9QJV+w55LVrY=
|
||||
k8s.io/apiserver v0.31.0/go.mod h1:KI9ox5Yu902iBnnyMmy7ajonhKnkeZYJhTZ/YI+WEMk=
|
||||
k8s.io/apiserver v0.31.1 h1:Sars5ejQDCRBY5f7R3QFHdqN3s61nhkpaX8/k1iEw1c=
|
||||
k8s.io/apiserver v0.31.1/go.mod h1:lzDhpeToamVZJmmFlaLwdYZwd7zB+WYRYIboqA1kGxM=
|
||||
k8s.io/client-go v0.31.1 h1:f0ugtWSbWpxHR7sjVpQwuvw9a3ZKLXX0u0itkFXufb0=
|
||||
k8s.io/client-go v0.31.1/go.mod h1:sKI8871MJN2OyeqRlmA4W4KM9KBdBUpDLu/43eGemCg=
|
||||
k8s.io/component-base v0.31.0 h1:/KIzGM5EvPNQcYgwq5NwoQBaOlVFrghoVGr8lG6vNRs=
|
||||
k8s.io/component-base v0.31.0/go.mod h1:TYVuzI1QmN4L5ItVdMSXKvH7/DtvIuas5/mm8YT3rTo=
|
||||
k8s.io/component-base v0.31.1 h1:UpOepcrX3rQ3ab5NB6g5iP0tvsgJWzxTyAo20sgYSy8=
|
||||
k8s.io/component-base v0.31.1/go.mod h1:WGeaw7t/kTsqpVTaCoVEtillbqAhF2/JgvO0LDOMa0w=
|
||||
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
|
||||
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||
k8s.io/kube-openapi v0.0.0-20240903163716-9e1beecbcb38 h1:1dWzkmJrrprYvjGwh9kEUxmcUV/CtNU8QM7h1FLWQOo=
|
||||
k8s.io/kube-openapi v0.0.0-20240903163716-9e1beecbcb38/go.mod h1:coRQXBK9NxO98XUv3ZD6AK3xzHCxV6+b7lrquKwaKzA=
|
||||
k8s.io/utils v0.0.0-20240902221715-702e33fdd3c3 h1:b2FmK8YH+QEwq/Sy2uAEhmqL5nPfGYbJOcaqjeYYZoA=
|
||||
k8s.io/utils v0.0.0-20240902221715-702e33fdd3c3/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
k8s.io/utils v0.0.0-20240921022957-49e7df575cb6 h1:MDF6h2H/h4tbzmtIKTuctcwZmY0tY9mD9fNT47QO6HI=
|
||||
k8s.io/utils v0.0.0-20240921022957-49e7df575cb6/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3 h1:2770sDpzrjjsAtVhSeUFseziht227YAWYHLGNM8QPwY=
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw=
|
||||
sigs.k8s.io/controller-runtime v0.19.0 h1:nWVM7aq+Il2ABxwiCizrVDSlmDcshi9llbaFbC0ji/Q=
|
||||
|
||||
@ -2,13 +2,30 @@ package instance
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
|
||||
barmanBackup "github.com/cloudnative-pg/barman-cloud/pkg/backup"
|
||||
barmanCapabilities "github.com/cloudnative-pg/barman-cloud/pkg/capabilities"
|
||||
barmanCredentials "github.com/cloudnative-pg/barman-cloud/pkg/credentials"
|
||||
cnpgv1 "github.com/cloudnative-pg/cloudnative-pg/api/v1"
|
||||
"github.com/cloudnative-pg/cloudnative-pg/pkg/conditions"
|
||||
"github.com/cloudnative-pg/cloudnative-pg/pkg/postgres"
|
||||
"github.com/cloudnative-pg/cloudnative-pg/pkg/resources"
|
||||
"github.com/cloudnative-pg/cnpg-i-machinery/pkg/pluginhelper/decoder"
|
||||
"github.com/cloudnative-pg/cnpg-i/pkg/backup"
|
||||
"github.com/cloudnative-pg/machinery/pkg/fileutils"
|
||||
"github.com/cloudnative-pg/machinery/pkg/log"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/tools/record"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
)
|
||||
|
||||
// BackupServiceImplementation is the implementation
|
||||
// of the Backup CNPG capability
|
||||
type BackupServiceImplementation struct {
|
||||
Client client.Client
|
||||
Recorder record.EventRecorder
|
||||
InstanceName string
|
||||
backup.UnimplementedBackupServer
|
||||
}
|
||||
|
||||
@ -30,7 +47,98 @@ func (b BackupServiceImplementation) GetCapabilities(
|
||||
}
|
||||
|
||||
// Backup implements the Backup interface
|
||||
func (b BackupServiceImplementation) Backup(_ context.Context, _ *backup.BackupRequest) (*backup.BackupResult, error) {
|
||||
// TODO implement me
|
||||
panic("implement me")
|
||||
func (b BackupServiceImplementation) Backup(
|
||||
ctx context.Context,
|
||||
req *backup.BackupRequest,
|
||||
) (*backup.BackupResult, error) {
|
||||
contextLogger := log.FromContext(ctx)
|
||||
backupObj, err := decoder.DecodeBackup(req.BackupDefinition)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cluster, err := decoder.DecodeClusterJSON(req.ClusterDefinition)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Update backup status in cluster conditions on startup
|
||||
if err := b.retryWithRefreshedCluster(ctx, cluster, func() error {
|
||||
// TODO: this condition is set only here, never removed or handled?
|
||||
return conditions.Patch(ctx, b.Client, cluster, cnpgv1.BackupStartingCondition)
|
||||
}); err != nil {
|
||||
contextLogger.Error(err, "Error changing backup condition (backup started)")
|
||||
// We do not terminate here because we could still have a good backup
|
||||
// even if we are unable to communicate with the Kubernetes API server
|
||||
}
|
||||
|
||||
if err := fileutils.EnsureDirectoryExists(postgres.BackupTemporaryDirectory); err != nil {
|
||||
contextLogger.Error(err, "Cannot create backup temporary directory", "err", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
capabilities, err := barmanCapabilities.CurrentCapabilities()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
backupCmd := barmanBackup.NewBackupCommand(
|
||||
cluster.Spec.Backup.BarmanObjectStore,
|
||||
capabilities,
|
||||
)
|
||||
env := os.Environ()
|
||||
env, err = barmanCredentials.EnvSetBackupCloudCredentials(
|
||||
ctx,
|
||||
b.Client,
|
||||
cluster.Namespace,
|
||||
cluster.Spec.Backup.BarmanObjectStore,
|
||||
env)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = backupCmd.Take(
|
||||
ctx,
|
||||
backupObj.Status.BackupName,
|
||||
backupObj.Status.ServerName,
|
||||
env,
|
||||
cluster,
|
||||
postgres.BackupTemporaryDirectory,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
contextLogger.Info("Backup completed")
|
||||
b.Recorder.Event(backupObj, "Normal", "Completed", "Backup completed")
|
||||
|
||||
// Set the status to completed
|
||||
backupObj.Status.SetAsCompleted()
|
||||
|
||||
executedBackupInfo, err := backupCmd.GetExecutedBackupInfo(
|
||||
ctx, backupObj.Status.BackupName, backupObj.Status.ServerName, cluster, env)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &backup.BackupResult{
|
||||
BackupId: executedBackupInfo.ID,
|
||||
BackupName: executedBackupInfo.BackupName,
|
||||
StartedAt: metav1.Time{Time: executedBackupInfo.BeginTime}.Unix(),
|
||||
StoppedAt: metav1.Time{Time: executedBackupInfo.EndTime}.Unix(),
|
||||
BeginWal: executedBackupInfo.BeginWal,
|
||||
EndWal: executedBackupInfo.EndWal,
|
||||
BeginLsn: executedBackupInfo.BeginLSN,
|
||||
EndLsn: executedBackupInfo.EndLSN,
|
||||
BackupLabelFile: nil,
|
||||
TablespaceMapFile: nil,
|
||||
InstanceId: b.InstanceName,
|
||||
Online: true,
|
||||
Metadata: nil,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (b *BackupServiceImplementation) retryWithRefreshedCluster(
|
||||
ctx context.Context,
|
||||
cluster *cnpgv1.Cluster,
|
||||
cb func() error,
|
||||
) error {
|
||||
return resources.RetryWithRefreshedResource(ctx, b.Client, cluster, cb)
|
||||
}
|
||||
|
||||
@ -14,8 +14,8 @@ import (
|
||||
// IdentityImplementation implements IdentityServer
|
||||
type IdentityImplementation struct {
|
||||
identity.UnimplementedIdentityServer
|
||||
BarmanObjectKey client.ObjectKey
|
||||
Client client.Client
|
||||
WALConfigurationKey client.ObjectKey
|
||||
Client client.Client
|
||||
}
|
||||
|
||||
// GetPluginMetadata implements IdentityServer
|
||||
@ -57,8 +57,8 @@ func (i IdentityImplementation) Probe(
|
||||
_ *identity.ProbeRequest,
|
||||
) (*identity.ProbeResponse, error) {
|
||||
var obj barmancloudv1.ObjectStore
|
||||
if err := i.Client.Get(ctx, i.BarmanObjectKey, &obj); err != nil {
|
||||
return nil, fmt.Errorf("while fetching object store %s: %w", i.BarmanObjectKey.Name, err)
|
||||
if err := i.Client.Get(ctx, i.WALConfigurationKey, &obj); err != nil {
|
||||
return nil, fmt.Errorf("while fetching object store %s: %w", i.WALConfigurationKey.Name, err)
|
||||
}
|
||||
|
||||
return &identity.ProbeResponse{
|
||||
|
||||
@ -7,20 +7,22 @@ import (
|
||||
"github.com/cloudnative-pg/cnpg-i/pkg/backup"
|
||||
"github.com/cloudnative-pg/cnpg-i/pkg/wal"
|
||||
"google.golang.org/grpc"
|
||||
"k8s.io/client-go/tools/record"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
)
|
||||
|
||||
// CNPGI is the implementation of the PostgreSQL sidecar
|
||||
type CNPGI struct {
|
||||
Client client.Client
|
||||
BarmanObjectKey client.ObjectKey
|
||||
ClusterObjectKey client.ObjectKey
|
||||
PGDataPath string
|
||||
PGWALPath string
|
||||
SpoolDirectory string
|
||||
ServerCertPath string
|
||||
ServerKeyPath string
|
||||
ClientCertPath string
|
||||
Client client.Client
|
||||
Recorder record.EventRecorder
|
||||
WALConfigurationKey client.ObjectKey
|
||||
ClusterObjectKey client.ObjectKey
|
||||
PGDataPath string
|
||||
PGWALPath string
|
||||
SpoolDirectory string
|
||||
ServerCertPath string
|
||||
ServerKeyPath string
|
||||
ClientCertPath string
|
||||
// mutually exclusive with pluginPath
|
||||
ServerAddress string
|
||||
// mutually exclusive with serverAddress
|
||||
@ -32,7 +34,7 @@ type CNPGI struct {
|
||||
func (c *CNPGI) Start(ctx context.Context) error {
|
||||
enrich := func(server *grpc.Server) error {
|
||||
wal.RegisterWALServer(server, WALServiceImplementation{
|
||||
BarmanObjectKey: c.BarmanObjectKey,
|
||||
BarmanObjectKey: c.WALConfigurationKey,
|
||||
ClusterObjectKey: c.ClusterObjectKey,
|
||||
InstanceName: c.InstanceName,
|
||||
Client: c.Client,
|
||||
@ -40,14 +42,18 @@ func (c *CNPGI) Start(ctx context.Context) error {
|
||||
PGDataPath: c.PGDataPath,
|
||||
PGWALPath: c.PGWALPath,
|
||||
})
|
||||
backup.RegisterBackupServer(server, BackupServiceImplementation{})
|
||||
backup.RegisterBackupServer(server, BackupServiceImplementation{
|
||||
Client: c.Client,
|
||||
Recorder: c.Recorder,
|
||||
InstanceName: c.InstanceName,
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
srv := http.Server{
|
||||
IdentityImpl: IdentityImplementation{
|
||||
Client: c.Client,
|
||||
BarmanObjectKey: c.BarmanObjectKey,
|
||||
Client: c.Client,
|
||||
WALConfigurationKey: c.WALConfigurationKey,
|
||||
},
|
||||
Enrichers: []http.ServerEnricher{enrich},
|
||||
ServerCertPath: c.ServerCertPath,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user