backup(longhorn): create snapshot before snapshot backup
This commit is contained in:
parent
42fa848a82
commit
e8add01511
@ -85,11 +85,25 @@ type snapshotInput struct {
|
||||
BackupMode string `json:"backupMode,omitempty"`
|
||||
}
|
||||
|
||||
type snapshotCreateInput struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Labels map[string]string `json:"labels,omitempty"`
|
||||
}
|
||||
|
||||
type pvcCreateInput struct {
|
||||
Namespace string `json:"namespace"`
|
||||
PVCName string `json:"pvcName"`
|
||||
}
|
||||
|
||||
func (c *Client) CreateSnapshot(ctx context.Context, volume, name string, labels map[string]string) error {
|
||||
path := fmt.Sprintf("%s/v1/volumes/%s?action=snapshotCreate", c.baseURL, url.PathEscape(volume))
|
||||
input := snapshotCreateInput{
|
||||
Name: name,
|
||||
Labels: labels,
|
||||
}
|
||||
return c.doJSON(ctx, http.MethodPost, path, input, nil)
|
||||
}
|
||||
|
||||
func (c *Client) SnapshotBackup(ctx context.Context, volume, name string, labels map[string]string, backupMode string) (*Volume, error) {
|
||||
path := fmt.Sprintf("%s/v1/volumes/%s?action=snapshotBackup", c.baseURL, url.PathEscape(volume))
|
||||
input := snapshotInput{
|
||||
|
||||
@ -35,6 +35,7 @@ type kubeClient interface {
|
||||
}
|
||||
|
||||
type longhornClient interface {
|
||||
CreateSnapshot(ctx context.Context, volume, name string, labels map[string]string) error
|
||||
SnapshotBackup(ctx context.Context, volume, name string, labels map[string]string, backupMode string) (*longhorn.Volume, error)
|
||||
GetVolume(ctx context.Context, volume string) (*longhorn.Volume, error)
|
||||
CreateVolumeFromBackup(ctx context.Context, name, size string, replicas int, backupURL string) (*longhorn.Volume, error)
|
||||
@ -620,6 +621,9 @@ func (s *Server) executeBackup(ctx context.Context, req api.BackupRequest, reque
|
||||
"soteria.bstein.dev/pvc": req.PVC,
|
||||
"soteria.bstein.dev/requested-by": requester,
|
||||
}
|
||||
if err := s.longhorn.CreateSnapshot(ctx, volumeName, backupID, labels); err != nil {
|
||||
return api.BackupResponse{}, "backend_error", err
|
||||
}
|
||||
if _, err := s.longhorn.SnapshotBackup(ctx, volumeName, backupID, labels, s.cfg.LonghornBackupMode); err != nil {
|
||||
return api.BackupResponse{}, "backend_error", err
|
||||
}
|
||||
|
||||
@ -68,10 +68,18 @@ func (f *fakeKubeClient) SaveSecretData(_ context.Context, _, _, key string, val
|
||||
}
|
||||
|
||||
type fakeLonghornClient struct {
|
||||
backups []longhorn.Backup
|
||||
backups []longhorn.Backup
|
||||
createSnapshotName string
|
||||
snapshotBackupName string
|
||||
}
|
||||
|
||||
func (f *fakeLonghornClient) CreateSnapshot(_ context.Context, volume, name string, labels map[string]string) error {
|
||||
f.createSnapshotName = name
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *fakeLonghornClient) SnapshotBackup(_ context.Context, volume, name string, labels map[string]string, backupMode string) (*longhorn.Volume, error) {
|
||||
f.snapshotBackupName = name
|
||||
return &longhorn.Volume{Name: volume}, nil
|
||||
}
|
||||
|
||||
@ -222,6 +230,38 @@ func TestRestoreRejectsSameSourceAndTarget(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestBackupCreatesSnapshotBeforeBackup(t *testing.T) {
|
||||
lh := &fakeLonghornClient{}
|
||||
srv := &Server{
|
||||
cfg: &config.Config{AuthRequired: false, BackupDriver: "longhorn", LonghornBackupMode: "incremental"},
|
||||
client: &fakeKubeClient{},
|
||||
longhorn: lh,
|
||||
metrics: newTelemetry(),
|
||||
}
|
||||
srv.handler = http.HandlerFunc(srv.route)
|
||||
|
||||
body := `{"namespace":"apps","pvc":"data","dry_run":false}`
|
||||
req := httptest.NewRequest(http.MethodPost, "/v1/backup", strings.NewReader(body))
|
||||
res := httptest.NewRecorder()
|
||||
srv.Handler().ServeHTTP(res, req)
|
||||
|
||||
if res.Code != http.StatusOK {
|
||||
t.Fatalf("expected 200, got %d: %s", res.Code, res.Body.String())
|
||||
}
|
||||
if lh.createSnapshotName == "" {
|
||||
t.Fatalf("expected snapshot creation call")
|
||||
}
|
||||
if lh.snapshotBackupName == "" {
|
||||
t.Fatalf("expected snapshot backup call")
|
||||
}
|
||||
if lh.createSnapshotName != lh.snapshotBackupName {
|
||||
t.Fatalf("expected same snapshot and backup name, got snapshot=%q backup=%q", lh.createSnapshotName, lh.snapshotBackupName)
|
||||
}
|
||||
if !strings.HasPrefix(lh.createSnapshotName, "soteria-backup-apps-data-") {
|
||||
t.Fatalf("unexpected generated backup name %q", lh.createSnapshotName)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMetricsStayPublic(t *testing.T) {
|
||||
srv := &Server{
|
||||
cfg: &config.Config{AuthRequired: true, AllowedGroups: []string{"admin"}},
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user