Skip to content

Support filesystem backup as well as blob store backup #1

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

Open
wants to merge 1 commit into
base: 1.52.0
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion api/v1beta1/foundationdbbackup_types.go
Original file line number Diff line number Diff line change
@@ -112,6 +112,8 @@ type FoundationDBBackupSpec struct {

// This is the configuration of the target blobstore for this backup.
BlobStoreConfiguration *BlobStoreConfiguration `json:"blobStoreConfiguration,omitempty"`
// This is the configuration of the target filesystem for this backup.
FSConfiguration *FSConfiguration `json:"fsConfiguration,omitempty"`
}

// FoundationDBBackupStatus describes the current status of the backup for a cluster.
@@ -209,6 +211,19 @@ type BlobStoreConfiguration struct {
URLParameters []URLParamater `json:"urlParameters,omitempty"`
}

// FSConfiguration describes the blob store configuration.
type FSConfiguration struct {
// The name for the backup.
// If empty defaults to .metadata.name.
// +kubebuilder:validation:MaxLength=1024
BackupName string `json:"backupName,omitempty"`

// The url to use with the backup destination.
// +kubebuilder:validation:MaxLength=255
// +kubebuilder:validation:Required
URL string `json:"url"`
}

// ShouldRun determines whether a backup should be running.
func (backup *FoundationDBBackup) ShouldRun() bool {
return backup.Spec.BackupState == "" || backup.Spec.BackupState == BackupStateRunning || backup.Spec.BackupState == BackupStatePaused
@@ -236,14 +251,18 @@ func (backup *FoundationDBBackup) Bucket() string {
// BackupName gets the name of the backup in the destination.
// This will fill in a default value if the backup name in the spec is empty.
func (backup *FoundationDBBackup) BackupName() string {
if backup.Spec.BackupName == "" && (backup.Spec.BlobStoreConfiguration == nil || backup.Spec.BlobStoreConfiguration.BackupName == "") {
if backup.Spec.BackupName == "" && (backup.Spec.BlobStoreConfiguration == nil || backup.Spec.BlobStoreConfiguration.BackupName == "") && (backup.Spec.FSConfiguration == nil || backup.Spec.FSConfiguration.BackupName == "") {
return backup.ObjectMeta.Name
}

if backup.Spec.BlobStoreConfiguration != nil && backup.Spec.BlobStoreConfiguration.BackupName != "" {
return backup.Spec.BlobStoreConfiguration.BackupName
}

if backup.Spec.FSConfiguration != nil && backup.Spec.FSConfiguration.BackupName != "" {
return backup.Spec.FSConfiguration.BackupName
}

return backup.Spec.BackupName
}

@@ -253,6 +272,11 @@ func (backup *FoundationDBBackup) BackupURL() string {
return backup.Spec.BlobStoreConfiguration.getURL(backup.BackupName(), backup.Bucket())
}

// mpatou: should we use file:// ?
if backup.Spec.FSConfiguration != nil {
return fmt.Sprintf("%s/%s", backup.Spec.FSConfiguration.URL, backup.BackupName())

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if this is a filesystem path, you should use

Suggested change
return fmt.Sprintf("%s/%s", backup.Spec.FSConfiguration.URL, backup.BackupName())
return path.Join(backup.Spec.FSConfiguration.URL, backup.BackupName())

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation of fdb indicates that you can use file:// I don't think it would work ?

}

return fmt.Sprintf("blobstore://%s/%s?bucket=%s", backup.Spec.AccountName, backup.BackupName(), backup.Bucket())
}

33 changes: 33 additions & 0 deletions api/v1beta1/foundationdbbackup_types_test.go
Original file line number Diff line number Diff line change
@@ -381,6 +381,39 @@ var _ = Describe("[api] FoundationDBBackup", func() {
},
},
"blobstore://account@account/mybackup?bucket=fdb-backups&secure_connection=0"),
Entry("A backup with a fs config and a backup name",
FoundationDBBackup{
ObjectMeta: metav1.ObjectMeta{
Name: "mybackup",
},
Spec: FoundationDBBackupSpec{
FSConfiguration: &FSConfiguration{
URL: "/some/path",
BackupName: "backup",
},
},
},
"/some/path/backup"),
Entry("A backup with a fs config and no specific name",
FoundationDBBackup{
ObjectMeta: metav1.ObjectMeta{
Name: "mybackup",
},
Spec: FoundationDBBackupSpec{
FSConfiguration: &FSConfiguration{
URL: "/some/path",
},
},
},
"/some/path/mybackup"),
Entry("A backup with just a metadata name will return a generic URL based on the backup name",
FoundationDBBackup{
ObjectMeta: metav1.ObjectMeta{
Name: "mybackup",
},
Spec: FoundationDBBackupSpec{},
},
"blobstore:///mybackup?bucket=fdb-backups"),
)
})
})
17 changes: 14 additions & 3 deletions api/v1beta1/foundationdbrestore_types.go
Original file line number Diff line number Diff line change
@@ -21,6 +21,7 @@
package v1beta1

import (
"fmt"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

@@ -63,6 +64,8 @@ type FoundationDBRestoreSpec struct {

// This is the configuration of the target blobstore for this backup.
BlobStoreConfiguration *BlobStoreConfiguration `json:"blobStoreConfiguration,omitempty"`
// This is the configuration of the target filesystem for this backup.
FSConfiguration *FSConfiguration `json:"fsConfiguration,omitempty"`

// CustomParameters defines additional parameters to pass to the backup
// agents.
@@ -93,18 +96,26 @@ type FoundationDBKeyRange struct {
// BackupName gets the name of the backup for the source backup.
// This will fill in a default value if the backup name in the spec is empty.
func (restore *FoundationDBRestore) BackupName() string {
if restore.Spec.BlobStoreConfiguration == nil || restore.Spec.BlobStoreConfiguration.BackupName == "" {
return restore.ObjectMeta.Name

if restore.Spec.BlobStoreConfiguration != nil && restore.Spec.BlobStoreConfiguration.BackupName != "" {
return restore.Spec.BlobStoreConfiguration.BackupName
}

if restore.Spec.FSConfiguration != nil && restore.Spec.FSConfiguration.BackupName != "" {
return restore.Spec.FSConfiguration.BackupName
}

return restore.Spec.BlobStoreConfiguration.BackupName
return restore.ObjectMeta.Name
}

// BackupURL gets the destination url of the backup.
func (restore *FoundationDBRestore) BackupURL() string {
if restore.Spec.BlobStoreConfiguration != nil {
return restore.Spec.BlobStoreConfiguration.getURL(restore.BackupName(), restore.Spec.BlobStoreConfiguration.BucketName())
}
if restore.Spec.FSConfiguration != nil {
return fmt.Sprintf("%s/%s", restore.Spec.FSConfiguration.URL, restore.BackupName())

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if this is a filesystem path, you should use

Suggested change
return fmt.Sprintf("%s/%s", restore.Spec.FSConfiguration.URL, restore.BackupName())
return path.Join(restore.Spec.FSConfiguration.URL, restore.BackupName())

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above ?

}

return restore.Spec.BackupURL
}
67 changes: 50 additions & 17 deletions api/v1beta1/foundationdbrestore_types_test.go
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
/*
* foundationdbbrestore_types_test.go
*
* This source file is part of the FoundationDB open source project
*
* Copyright 2020-2021 Apple Inc. and the FoundationDB project authors
*
* 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.
* foundationdbbrestore_types_test.go
*
* This source file is part of the FoundationDB open source project
*
* Copyright 2020-2021 Apple Inc. and the FoundationDB project authors
*
* 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 v1beta1
@@ -126,6 +126,39 @@ var _ = Describe("[api] FoundationDBRestore", func() {
},
},
"blobstore://account@account/mybackup?bucket=fdb-backups&secure_connection=0"),
Entry("A restore with a fs config and a backup name",
FoundationDBRestore{
ObjectMeta: metav1.ObjectMeta{
Name: "mybackup",
},
Spec: FoundationDBRestoreSpec{
FSConfiguration: &FSConfiguration{
URL: "/some/path",
BackupName: "backup",
},
},
},
"/some/path/backup"),
Entry("A restore with a fs config and no specific name",
FoundationDBRestore{
ObjectMeta: metav1.ObjectMeta{
Name: "mybackup",
},
Spec: FoundationDBRestoreSpec{
FSConfiguration: &FSConfiguration{
URL: "/some/path",
},
},
},
"/some/path/mybackup"),
Entry("A restore with just a metadata name will return an empty name",
FoundationDBRestore{
ObjectMeta: metav1.ObjectMeta{
Name: "mybackup",
},
Spec: FoundationDBRestoreSpec{},
},
""),
)
})
})
36 changes: 31 additions & 5 deletions api/v1beta2/foundationdbbackup_types.go
Original file line number Diff line number Diff line change
@@ -95,6 +95,8 @@ type FoundationDBBackupSpec struct {

// This is the configuration of the target blobstore for this backup.
BlobStoreConfiguration *BlobStoreConfiguration `json:"blobStoreConfiguration,omitempty"`
// This is the configuration of the target filesystem for this backup.
FSConfiguration *FSConfiguration `json:"fsConfiguration,omitempty"`

// MainContainer defines customization for the foundationdb container.
MainContainer ContainerOverrides `json:"mainContainer,omitempty"`
@@ -211,6 +213,19 @@ type BlobStoreConfiguration struct {
URLParameters []URLParameter `json:"urlParameters,omitempty"`
}

// FSConfiguration describes the blob store configuration.
type FSConfiguration struct {
// The name for the backup.
// If empty defaults to .metadata.name.
// +kubebuilder:validation:MaxLength=1024
BackupName string `json:"backupName,omitempty"`

// The url to use with the backup destination.
// +kubebuilder:validation:MaxLength=255
// +kubebuilder:validation:Required
URL string `json:"url"`
}

// ShouldRun determines whether a backup should be running.
func (backup *FoundationDBBackup) ShouldRun() bool {
return backup.Spec.BackupState == "" || backup.Spec.BackupState == BackupStateRunning || backup.Spec.BackupState == BackupStatePaused
@@ -224,7 +239,7 @@ func (backup *FoundationDBBackup) ShouldBePaused() bool {
// Bucket gets the bucket this backup will use.
// This will fill in a default value if the bucket in the spec is empty.
func (backup *FoundationDBBackup) Bucket() string {
if backup.Spec.BlobStoreConfiguration.Bucket == "" {
if backup.Spec.BlobStoreConfiguration == nil || backup.Spec.BlobStoreConfiguration.Bucket == "" {
return "fdb-backups"
}

@@ -234,16 +249,27 @@ func (backup *FoundationDBBackup) Bucket() string {
// BackupName gets the name of the backup in the destination.
// This will fill in a default value if the backup name in the spec is empty.
func (backup *FoundationDBBackup) BackupName() string {
if backup.Spec.BlobStoreConfiguration.BackupName == "" {
return backup.ObjectMeta.Name
if backup.Spec.BlobStoreConfiguration != nil && backup.Spec.BlobStoreConfiguration.BackupName != "" {
return backup.Spec.BlobStoreConfiguration.BackupName
}

if backup.Spec.FSConfiguration != nil && backup.Spec.FSConfiguration.BackupName != "" {
return backup.Spec.FSConfiguration.BackupName
}

return backup.Spec.BlobStoreConfiguration.BackupName
return backup.ObjectMeta.Name
}

// BackupURL gets the destination url of the backup.
func (backup *FoundationDBBackup) BackupURL() string {
return backup.Spec.BlobStoreConfiguration.getURL(backup.BackupName(), backup.Bucket())
if backup.Spec.BlobStoreConfiguration != nil {
return backup.Spec.BlobStoreConfiguration.getURL(backup.BackupName(), backup.Bucket())
}
// mpatou: should we use file:// ?
if backup.Spec.FSConfiguration != nil {
return fmt.Sprintf("%s/%s", backup.Spec.FSConfiguration.URL, backup.BackupName())

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if this is a filesystem path, you should use

Suggested change
return fmt.Sprintf("%s/%s", backup.Spec.FSConfiguration.URL, backup.BackupName())
return path.Join(backup.Spec.FSConfiguration.URL, backup.BackupName())

}
return ""
}

// SnapshotPeriodSeconds gets the period between snapshots for a backup.
25 changes: 22 additions & 3 deletions api/v1beta2/foundationdbrestore_types.go
Original file line number Diff line number Diff line change
@@ -17,6 +17,7 @@ limitations under the License.
package v1beta2

import (
"fmt"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

@@ -55,6 +56,8 @@ type FoundationDBRestoreSpec struct {

// This is the configuration of the target blobstore for this backup.
BlobStoreConfiguration *BlobStoreConfiguration `json:"blobStoreConfiguration,omitempty"`
// This is the configuration of the target filesystem for this backup.
FSConfiguration *FSConfiguration `json:"fsConfiguration,omitempty"`

// CustomParameters defines additional parameters to pass to the backup
// agents.
@@ -85,16 +88,32 @@ type FoundationDBKeyRange struct {
// BackupName gets the name of the backup for the source backup.
// This will fill in a default value if the backup name in the spec is empty.
func (restore *FoundationDBRestore) BackupName() string {
if restore.Spec.BlobStoreConfiguration == nil || restore.Spec.BlobStoreConfiguration.BackupName == "" {
if (restore.Spec.BlobStoreConfiguration == nil || restore.Spec.BlobStoreConfiguration.BackupName == "") && (restore.Spec.FSConfiguration == nil || restore.Spec.FSConfiguration.BackupName == "") {
return restore.ObjectMeta.Name
}

return restore.Spec.BlobStoreConfiguration.BackupName
if restore.Spec.BlobStoreConfiguration != nil && restore.Spec.BlobStoreConfiguration.BackupName != "" {
return restore.Spec.BlobStoreConfiguration.BackupName
}

if restore.Spec.FSConfiguration != nil && restore.Spec.FSConfiguration.BackupName != "" {
return restore.Spec.FSConfiguration.BackupName
}

return ""
}

// BackupURL gets the destination url of the backup.
func (restore *FoundationDBRestore) BackupURL() string {
return restore.Spec.BlobStoreConfiguration.getURL(restore.BackupName(), restore.Spec.BlobStoreConfiguration.BucketName())
if restore.Spec.BlobStoreConfiguration != nil {
return restore.Spec.BlobStoreConfiguration.getURL(restore.BackupName(), restore.Spec.BlobStoreConfiguration.BucketName())
}

if restore.Spec.FSConfiguration != nil {
return fmt.Sprintf("%s/%s", restore.Spec.FSConfiguration.URL, restore.BackupName())

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as previous

}

return ""
}

func init() {
33 changes: 33 additions & 0 deletions api/v1beta2/foundationdbrestore_types_test.go
Original file line number Diff line number Diff line change
@@ -116,6 +116,39 @@ var _ = Describe("[api] FoundationDBRestore", func() {
},
},
"blobstore://account@account:80/mybackup?bucket=fdb-backups&secure_connection=0"),
Entry("A restore with a fs config and a backup name",
FoundationDBRestore{
ObjectMeta: metav1.ObjectMeta{
Name: "mybackup",
},
Spec: FoundationDBRestoreSpec{
FSConfiguration: &FSConfiguration{
URL: "/some/path",
BackupName: "backup",
},
},
},
"/some/path/backup"),
Entry("A restore with a fs config and no specific name",
FoundationDBRestore{
ObjectMeta: metav1.ObjectMeta{
Name: "mybackup",
},
Spec: FoundationDBRestoreSpec{
FSConfiguration: &FSConfiguration{
URL: "/some/path",
},
},
},
"/some/path/mybackup"),
Entry("A restore with just a metadata name will return an empty name",
FoundationDBRestore{
ObjectMeta: metav1.ObjectMeta{
Name: "mybackup",
},
Spec: FoundationDBRestoreSpec{},
},
""),
)
})
})
Loading