databasus--databasus
75f3dd141c
CodeQL / Analyze (go) (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CI and Release / lint-frontend (push) Has been cancelled
CI and Release / dockerfile-scan (push) Has been cancelled
CI and Release / test-frontend (push) Has been cancelled
CI and Release / lint-verification-agent (push) Has been cancelled
CI and Release / test-verification-agent (push) Has been cancelled
CI and Release / e2e-verification-agent (push) Has been cancelled
CI and Release / test-backend (push) Has been cancelled
CI and Release / build-dev-image (push) Has been cancelled
CI and Release / push-dev-image (push) Has been cancelled
CI and Release / build-image (push) Has been cancelled
CI and Release / build-verification-image (push) Has been cancelled
CI and Release / determine-version (push) Has been cancelled
CI and Release / push-image (push) Has been cancelled
CI and Release / push-verification-image (12) (push) Has been cancelled
CI and Release / lint-backend (push) Has been cancelled
CI and Release / push-verification-image (17) (push) Has been cancelled
CI and Release / push-verification-image (18) (push) Has been cancelled
CI and Release / release (push) Has been cancelled
CI and Release / publish-helm-chart (push) Has been cancelled
CI and Release / push-verification-image (13) (push) Has been cancelled
CI and Release / push-verification-image (14) (push) Has been cancelled
CI and Release / push-verification-image (15) (push) Has been cancelled
CI and Release / push-verification-image (16) (push) Has been cancelled
351 行
9.5 KiB
Go
351 行
9.5 KiB
Go
package backups_config_physical
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
backups_core_enums "databasus-backend/internal/features/backups/backups/core/enums"
|
|
postgresql_physical "databasus-backend/internal/features/databases/databases/postgresql/physical"
|
|
"databasus-backend/internal/features/intervals"
|
|
)
|
|
|
|
func dailyAt(hhmm string) intervals.Interval {
|
|
return intervals.Interval{
|
|
Type: intervals.IntervalDaily,
|
|
TimeOfDay: new(hhmm),
|
|
}
|
|
}
|
|
|
|
func hourly() intervals.Interval {
|
|
return intervals.Interval{Type: intervals.IntervalHourly}
|
|
}
|
|
|
|
func weeklyMondayAt(hhmm string) intervals.Interval {
|
|
return intervals.Interval{
|
|
Type: intervals.IntervalWeekly,
|
|
Weekday: new(1),
|
|
TimeOfDay: new(hhmm),
|
|
}
|
|
}
|
|
|
|
func validFullOnlyConfig() *PhysicalBackupConfig {
|
|
return &PhysicalBackupConfig{
|
|
IsBackupsEnabled: true,
|
|
FullBackupInterval: dailyAt("02:00"),
|
|
Retention: RetentionFullBackups,
|
|
FullBackupsRetention: FullBackupsRetention{
|
|
Policy: FullBackupsRetentionPolicyGfs,
|
|
GfsDays: 7,
|
|
},
|
|
Encryption: backups_core_enums.BackupEncryptionNone,
|
|
PostgresqlPhysical: &postgresql_physical.PostgresqlPhysicalDatabase{
|
|
BackupType: postgresql_physical.BackupTypeFullOnly,
|
|
},
|
|
}
|
|
}
|
|
|
|
func validFullIncrementalConfig() *PhysicalBackupConfig {
|
|
return &PhysicalBackupConfig{
|
|
IsBackupsEnabled: true,
|
|
FullBackupInterval: weeklyMondayAt("02:00"),
|
|
IncrementalBackupInterval: dailyAt("02:00"),
|
|
Retention: RetentionChains,
|
|
ChainsRetention: ChainsRetention{Count: 3},
|
|
Encryption: backups_core_enums.BackupEncryptionNone,
|
|
PostgresqlPhysical: &postgresql_physical.PostgresqlPhysicalDatabase{
|
|
BackupType: postgresql_physical.BackupTypeFullAndIncremental,
|
|
},
|
|
}
|
|
}
|
|
|
|
func validFullIncrementalWalStreamConfig() *PhysicalBackupConfig {
|
|
return &PhysicalBackupConfig{
|
|
IsBackupsEnabled: true,
|
|
FullBackupInterval: weeklyMondayAt("02:00"),
|
|
IncrementalBackupInterval: dailyAt("02:00"),
|
|
Retention: RetentionChains,
|
|
ChainsRetention: ChainsRetention{Count: 3},
|
|
WalLagThresholdBytes: 16 * 1024 * 1024,
|
|
Encryption: backups_core_enums.BackupEncryptionNone,
|
|
PostgresqlPhysical: &postgresql_physical.PostgresqlPhysicalDatabase{
|
|
BackupType: postgresql_physical.BackupTypeFullIncrementalAndWalStream,
|
|
},
|
|
}
|
|
}
|
|
|
|
func Test_Validate_RejectsBlankFullBackupInterval(t *testing.T) {
|
|
c := validFullOnlyConfig()
|
|
c.FullBackupInterval = intervals.Interval{}
|
|
|
|
assert.Error(t, c.Validate())
|
|
}
|
|
|
|
func Test_Validate_RejectsUnknownEncryption(t *testing.T) {
|
|
c := validFullOnlyConfig()
|
|
c.Encryption = "GIBBERISH"
|
|
|
|
assert.Error(t, c.Validate())
|
|
}
|
|
|
|
func Test_Validate_RejectsNegativeWalLagThreshold(t *testing.T) {
|
|
c := validFullIncrementalWalStreamConfig()
|
|
c.WalLagThresholdBytes = -1
|
|
|
|
assert.Error(t, c.Validate())
|
|
}
|
|
|
|
func Test_Validate_FullOnly_RejectsIncrementalIntervalSet(t *testing.T) {
|
|
c := validFullOnlyConfig()
|
|
c.IncrementalBackupInterval = hourly()
|
|
|
|
err := c.Validate()
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "incremental")
|
|
}
|
|
|
|
func Test_Validate_FullOnly_AcceptsFullBackupsLastN(t *testing.T) {
|
|
c := validFullOnlyConfig()
|
|
c.FullBackupsRetention = FullBackupsRetention{
|
|
Policy: FullBackupsRetentionPolicyLastN,
|
|
Count: 5,
|
|
}
|
|
|
|
assert.NoError(t, c.Validate())
|
|
}
|
|
|
|
func Test_Validate_FullOnly_AcceptsFullBackupsGfs(t *testing.T) {
|
|
c := validFullOnlyConfig()
|
|
c.FullBackupsRetention = FullBackupsRetention{
|
|
Policy: FullBackupsRetentionPolicyGfs,
|
|
GfsDays: 7,
|
|
}
|
|
|
|
assert.NoError(t, c.Validate())
|
|
}
|
|
|
|
func Test_Validate_FullOnly_RejectsChainsRetention(t *testing.T) {
|
|
c := validFullOnlyConfig()
|
|
c.Retention = RetentionChains
|
|
c.ChainsRetention = ChainsRetention{Count: 3}
|
|
c.FullBackupsRetention = FullBackupsRetention{}
|
|
|
|
err := c.Validate()
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "FULL_ONLY")
|
|
}
|
|
|
|
func Test_Validate_FullOnly_RejectsChainsAndFullBackupsRetention(t *testing.T) {
|
|
c := validFullOnlyConfig()
|
|
c.Retention = RetentionChainsAndFullBackups
|
|
c.ChainsRetention = ChainsRetention{Count: 3}
|
|
|
|
err := c.Validate()
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "FULL_ONLY")
|
|
}
|
|
|
|
func Test_Validate_FullOnly_RejectsWalLagThresholdSet(t *testing.T) {
|
|
c := validFullOnlyConfig()
|
|
c.WalLagThresholdBytes = 1024
|
|
|
|
assert.Error(t, c.Validate())
|
|
}
|
|
|
|
func Test_Validate_FullIncremental_RejectsBlankIncrementalInterval(t *testing.T) {
|
|
c := validFullIncrementalConfig()
|
|
c.IncrementalBackupInterval = intervals.Interval{}
|
|
|
|
assert.Error(t, c.Validate())
|
|
}
|
|
|
|
func Test_Validate_FullIncremental_RejectsIncrementalCadenceEqualToFull(t *testing.T) {
|
|
c := validFullIncrementalConfig()
|
|
c.FullBackupInterval = dailyAt("02:00")
|
|
c.IncrementalBackupInterval = dailyAt("12:00")
|
|
|
|
err := c.Validate()
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "more frequent")
|
|
}
|
|
|
|
func Test_Validate_FullIncremental_RejectsIncrementalCadenceLargerThanFull(t *testing.T) {
|
|
c := validFullIncrementalConfig()
|
|
c.FullBackupInterval = hourly()
|
|
c.IncrementalBackupInterval = dailyAt("02:00")
|
|
|
|
err := c.Validate()
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "more frequent")
|
|
}
|
|
|
|
func Test_Validate_FullIncremental_AcceptsChainsRetention(t *testing.T) {
|
|
c := validFullIncrementalConfig()
|
|
c.Retention = RetentionChains
|
|
c.ChainsRetention = ChainsRetention{Count: 3}
|
|
c.FullBackupsRetention = FullBackupsRetention{}
|
|
|
|
assert.NoError(t, c.Validate())
|
|
}
|
|
|
|
func Test_Validate_FullIncremental_AcceptsChainsAndFullBackupsRetention(t *testing.T) {
|
|
c := validFullIncrementalConfig()
|
|
c.Retention = RetentionChainsAndFullBackups
|
|
c.ChainsRetention = ChainsRetention{Count: 3}
|
|
c.FullBackupsRetention = FullBackupsRetention{
|
|
Policy: FullBackupsRetentionPolicyGfs,
|
|
GfsWeeks: 4,
|
|
}
|
|
|
|
assert.NoError(t, c.Validate())
|
|
}
|
|
|
|
func Test_Validate_FullIncremental_RejectsFullBackupsOnlyRetention(t *testing.T) {
|
|
c := validFullIncrementalConfig()
|
|
c.Retention = RetentionFullBackups
|
|
c.ChainsRetention = ChainsRetention{}
|
|
c.FullBackupsRetention = FullBackupsRetention{
|
|
Policy: FullBackupsRetentionPolicyLastN,
|
|
Count: 5,
|
|
}
|
|
|
|
err := c.Validate()
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "CHAINS")
|
|
}
|
|
|
|
func Test_Validate_FullIncremental_RejectsWalLagThresholdSet(t *testing.T) {
|
|
c := validFullIncrementalConfig()
|
|
c.WalLagThresholdBytes = 1024
|
|
|
|
assert.Error(t, c.Validate())
|
|
}
|
|
|
|
func Test_Validate_RejectsChainsRetentionWithZeroCount(t *testing.T) {
|
|
c := validFullIncrementalConfig()
|
|
c.Retention = RetentionChains
|
|
c.ChainsRetention = ChainsRetention{Count: 0}
|
|
|
|
err := c.Validate()
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "chains_retention.count")
|
|
}
|
|
|
|
func Test_Validate_RejectsChainsRetentionWithFullBackupsFieldsSet(t *testing.T) {
|
|
c := validFullIncrementalConfig()
|
|
c.Retention = RetentionChains
|
|
c.ChainsRetention = ChainsRetention{Count: 3}
|
|
c.FullBackupsRetention = FullBackupsRetention{
|
|
Policy: FullBackupsRetentionPolicyLastN,
|
|
Count: 5,
|
|
}
|
|
|
|
err := c.Validate()
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "full_backups_retention")
|
|
}
|
|
|
|
func Test_Validate_RejectsFullBackupsLastNWithZeroCount(t *testing.T) {
|
|
c := validFullOnlyConfig()
|
|
c.FullBackupsRetention = FullBackupsRetention{
|
|
Policy: FullBackupsRetentionPolicyLastN,
|
|
Count: 0,
|
|
}
|
|
|
|
err := c.Validate()
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "count > 0")
|
|
}
|
|
|
|
func Test_Validate_RejectsFullBackupsLastNWithGfsBucketsSet(t *testing.T) {
|
|
c := validFullOnlyConfig()
|
|
c.FullBackupsRetention = FullBackupsRetention{
|
|
Policy: FullBackupsRetentionPolicyLastN,
|
|
Count: 5,
|
|
GfsDays: 3,
|
|
}
|
|
|
|
err := c.Validate()
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "GFS buckets")
|
|
}
|
|
|
|
func Test_Validate_RejectsFullBackupsGfsWithAllZeroBuckets(t *testing.T) {
|
|
c := validFullOnlyConfig()
|
|
c.FullBackupsRetention = FullBackupsRetention{
|
|
Policy: FullBackupsRetentionPolicyGfs,
|
|
}
|
|
|
|
err := c.Validate()
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "bucket")
|
|
}
|
|
|
|
func Test_Validate_RejectsFullBackupsGfsWithCountSet(t *testing.T) {
|
|
c := validFullOnlyConfig()
|
|
c.FullBackupsRetention = FullBackupsRetention{
|
|
Policy: FullBackupsRetentionPolicyGfs,
|
|
Count: 3,
|
|
GfsDays: 7,
|
|
}
|
|
|
|
err := c.Validate()
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "count")
|
|
}
|
|
|
|
func Test_Validate_RejectsFullBackupsRetentionWithChainsCountSet(t *testing.T) {
|
|
c := validFullOnlyConfig()
|
|
c.ChainsRetention = ChainsRetention{Count: 3}
|
|
|
|
err := c.Validate()
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "chains_retention")
|
|
}
|
|
|
|
func Test_Validate_RejectsUnknownRetention(t *testing.T) {
|
|
c := validFullOnlyConfig()
|
|
c.Retention = "GIBBERISH"
|
|
|
|
assert.Error(t, c.Validate())
|
|
}
|
|
|
|
func Test_Validate_RejectsUnknownFullBackupsPolicy(t *testing.T) {
|
|
c := validFullOnlyConfig()
|
|
c.FullBackupsRetention = FullBackupsRetention{
|
|
Policy: "GIBBERISH",
|
|
GfsDays: 7,
|
|
}
|
|
|
|
assert.Error(t, c.Validate())
|
|
}
|
|
|
|
func Test_Validate_FullIncrementalWalStream_RejectsZeroWalLagThreshold(t *testing.T) {
|
|
c := validFullIncrementalWalStreamConfig()
|
|
c.WalLagThresholdBytes = 0
|
|
|
|
err := c.Validate()
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "wal lag threshold")
|
|
}
|
|
|
|
func Test_Validate_FullIncrementalWalStream_AcceptsValidConfig(t *testing.T) {
|
|
assert.NoError(t, validFullIncrementalWalStreamConfig().Validate())
|
|
}
|
|
|
|
func Test_Validate_RejectsUnknownBackupType(t *testing.T) {
|
|
c := validFullOnlyConfig()
|
|
c.PostgresqlPhysical.BackupType = "GIBBERISH"
|
|
|
|
assert.Error(t, c.Validate())
|
|
}
|
|
|
|
func Test_Validate_RejectsMissingPostgresqlPhysicalPreload(t *testing.T) {
|
|
c := validFullOnlyConfig()
|
|
c.PostgresqlPhysical = nil
|
|
|
|
err := c.Validate()
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "preloaded")
|
|
}
|