Support time ranges expressed in hours in snapshot retention policies
Make restic forget --keep-within accept time ranges measured in hours and choose accordingly which snapshots to keep and which to forget. Add relative tests.
This commit is contained in:
parent
7486bfea5b
commit
71891b340c
6 changed files with 1661 additions and 2 deletions
|
@ -59,7 +59,7 @@ func init() {
|
|||
f.IntVarP(&forgetOptions.Weekly, "keep-weekly", "w", 0, "keep the last `n` weekly snapshots")
|
||||
f.IntVarP(&forgetOptions.Monthly, "keep-monthly", "m", 0, "keep the last `n` monthly snapshots")
|
||||
f.IntVarP(&forgetOptions.Yearly, "keep-yearly", "y", 0, "keep the last `n` yearly snapshots")
|
||||
f.VarP(&forgetOptions.Within, "keep-within", "", "keep snapshots that are older than `duration` (eg. 1y5m7d) relative to the latest snapshot")
|
||||
f.VarP(&forgetOptions.Within, "keep-within", "", "keep snapshots that are newer than `duration` (eg. 1y5m7d2h) relative to the latest snapshot")
|
||||
|
||||
f.Var(&forgetOptions.KeepTags, "keep-tag", "keep snapshots with this `taglist` (can be specified multiple times)")
|
||||
f.StringVar(&forgetOptions.Host, "host", "", "only consider snapshots with the given `host`")
|
||||
|
|
|
@ -196,7 +196,7 @@ func ApplyPolicy(list Snapshots, p ExpirePolicy) (keep, remove Snapshots, reason
|
|||
|
||||
// If the timestamp of the snapshot is within the range, then keep it.
|
||||
if !p.Within.Zero() {
|
||||
t := latest.AddDate(-p.Within.Years, -p.Within.Months, -p.Within.Days)
|
||||
t := latest.AddDate(-p.Within.Years, -p.Within.Months, -p.Within.Days).Add(time.Hour * time.Duration(-p.Within.Hours))
|
||||
if cur.Time.After(t) {
|
||||
keepSnap = true
|
||||
keepSnapReasons = append(keepSnapReasons, fmt.Sprintf("within %v", p.Within))
|
||||
|
|
|
@ -225,6 +225,9 @@ func TestApplyPolicy(t *testing.T) {
|
|||
{Within: parseDuration("1m")},
|
||||
{Within: parseDuration("1m14d")},
|
||||
{Within: parseDuration("1y1d1m")},
|
||||
{Within: parseDuration("13d23h")},
|
||||
{Within: parseDuration("2m2h")},
|
||||
{Within: parseDuration("1y2m3d3h")},
|
||||
}
|
||||
|
||||
for i, p := range tests {
|
||||
|
|
150
internal/restic/testdata/policy_keep_snapshots_27
vendored
Normal file
150
internal/restic/testdata/policy_keep_snapshots_27
vendored
Normal file
|
@ -0,0 +1,150 @@
|
|||
{
|
||||
"keep": [
|
||||
{
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-09T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-08T20:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-07T10:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-06T08:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-05T09:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T16:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
}
|
||||
],
|
||||
"reasons": [
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 13d23h"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 13d23h"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-12T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 13d23h"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-09T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 13d23h"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-08T20:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 13d23h"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-07T10:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 13d23h"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-06T08:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 13d23h"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-05T09:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 13d23h"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-04T16:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 13d23h"
|
||||
],
|
||||
"counters": {}
|
||||
}
|
||||
]
|
||||
}
|
374
internal/restic/testdata/policy_keep_snapshots_28
vendored
Normal file
374
internal/restic/testdata/policy_keep_snapshots_28
vendored
Normal file
|
@ -0,0 +1,374 @@
|
|||
{
|
||||
"keep": [
|
||||
{
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-09T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-08T20:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-07T10:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-06T08:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-05T09:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T16:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T12:30:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T12:28:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T12:24:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T12:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T11:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T10:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-03T07:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-01T07:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-01T01:03:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-01T01:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-11-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-11-21T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-11-20T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-11-18T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
}
|
||||
],
|
||||
"reasons": [
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 2m2h"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 2m2h"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-12T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 2m2h"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-09T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 2m2h"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-08T20:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 2m2h"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-07T10:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 2m2h"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-06T08:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 2m2h"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-05T09:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 2m2h"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-04T16:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 2m2h"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-04T12:30:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 2m2h"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-04T12:28:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 2m2h"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-04T12:24:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 2m2h"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-04T12:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 2m2h"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-04T11:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 2m2h"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-04T10:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 2m2h"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-03T07:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 2m2h"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-01T07:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 2m2h"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-01T01:03:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 2m2h"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-01T01:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 2m2h"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-11-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 2m2h"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-11-21T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 2m2h"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-11-20T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 2m2h"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-11-18T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 2m2h"
|
||||
],
|
||||
"counters": {}
|
||||
}
|
||||
]
|
||||
}
|
1132
internal/restic/testdata/policy_keep_snapshots_29
vendored
Normal file
1132
internal/restic/testdata/policy_keep_snapshots_29
vendored
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue