Code and tests to validate retention config (#5117)

Basic validation checks that make sure maintenance and retention options are consistent with each other. This at least makes sure retention is either enabled and maintenance extends locks or nothing is locked at all.

Going to be part of a set of PRs for validating the kopia config

---

#### Does this PR need a docs update or release note?

- [ ]  Yes, it's included
- [ ] 🕐 Yes, but in a later PR
- [x]  No

#### Type of change

- [x] 🌻 Feature
- [ ] 🐛 Bugfix
- [ ] 🗺️ Documentation
- [x] 🤖 Supportability/Tests
- [ ] 💻 CI/Deployment
- [ ] 🧹 Tech Debt/Cleanup

#### Test Plan

- [ ] 💪 Manual
- [x]  Unit test
- [ ] 💚 E2E
This commit is contained in:
ashmrtn 2024-01-25 16:09:35 -08:00 committed by GitHub
parent cc24f9b6e7
commit 683f163df1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 125 additions and 0 deletions

View File

@ -136,3 +136,34 @@ func (r *Opts) setBlobConfigMode(
return nil return nil
} }
// Verify checks that the config info in r passes kopia's retention validation
// checks when it comes to locking durations and that if retention is requested
// in the blob config blob then lock extension is also configured to run during
// maintenance. If rentention is not enabled in the blob config blob then lock
// extension should be disabled during maintenance.
func (r Opts) Verify(ctx context.Context) error {
if !r.blobCfg.IsRetentionEnabled() {
if r.params.ExtendObjectLocks {
return clues.NewWC(
ctx,
"retention disabled but maintenance lock extension enabled")
}
// Both disabled.
return nil
}
// Rest of function handles case where retention is enabled in the blob config
// blob.
if !r.params.ExtendObjectLocks {
return clues.NewWC(
ctx,
"retention enabled but maintenance lock extension disabled")
}
return clues.Stack(maintenance.CheckExtendRetention(
ctx,
r.blobCfg,
&r.params)).OrNil()
}

View File

@ -202,3 +202,97 @@ func (suite *OptsUnitSuite) TestSet() {
}) })
} }
} }
func (suite *OptsUnitSuite) TestVerify() {
mode := blob.Governance
fullCycleInterval := time.Hour * 24
duration := 2 * fullCycleInterval
table := []struct {
name string
input *retention.Opts
expectErr assert.ErrorAssertionFunc
}{
{
name: "ValidDisabled",
input: retention.OptsFromConfigs(
format.BlobStorageConfiguration{},
maintenance.Params{
FullCycle: maintenance.CycleParams{
Interval: fullCycleInterval,
},
ExtendObjectLocks: false,
}),
expectErr: assert.NoError,
},
{
name: "ValidEnabled",
input: retention.OptsFromConfigs(
format.BlobStorageConfiguration{
RetentionMode: mode,
RetentionPeriod: duration,
},
maintenance.Params{
FullCycle: maintenance.CycleParams{
Interval: fullCycleInterval,
},
ExtendObjectLocks: true,
}),
expectErr: assert.NoError,
},
{
name: "InvalidDuration",
input: retention.OptsFromConfigs(
format.BlobStorageConfiguration{
RetentionMode: mode,
RetentionPeriod: fullCycleInterval,
},
maintenance.Params{
FullCycle: maintenance.CycleParams{
Interval: fullCycleInterval,
},
ExtendObjectLocks: true,
}),
expectErr: assert.Error,
},
{
name: "InvalidNotExtending",
input: retention.OptsFromConfigs(
format.BlobStorageConfiguration{
RetentionMode: mode,
RetentionPeriod: duration,
},
maintenance.Params{
FullCycle: maintenance.CycleParams{
Interval: fullCycleInterval,
},
ExtendObjectLocks: false,
}),
expectErr: assert.Error,
},
{
name: "InvalidNotConfigured",
input: retention.OptsFromConfigs(
format.BlobStorageConfiguration{},
maintenance.Params{
FullCycle: maintenance.CycleParams{
Interval: fullCycleInterval,
},
ExtendObjectLocks: true,
}),
expectErr: assert.Error,
},
}
for _, test := range table {
suite.Run(test.name, func() {
t := suite.T()
ctx, flush := tester.NewContext(t)
t.Cleanup(flush)
err := test.input.Verify(ctx)
test.expectErr(t, err, clues.ToCore(err))
})
}
}