forked from TrueCloudLab/restic
Merge pull request #4764 from MichaelEischer/safe-keep-tag
Prevent unsafe uses of `forget --keep-tag`
This commit is contained in:
commit
3eeb6723cd
16 changed files with 1212 additions and 2149 deletions
17
changelog/unreleased/issue-4568
Normal file
17
changelog/unreleased/issue-4568
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
Bugfix: Prevent `forget --keep-tags invalid` from deleting all snapshots
|
||||||
|
|
||||||
|
Running `forget --keep-tags invalid`, where the tag `invalid` does not
|
||||||
|
exist in the repository, would remove all snapshots. This is especially
|
||||||
|
problematic if the tag name contains a typo.
|
||||||
|
|
||||||
|
The `forget` command now fails with an error if all snapshots in a snapshot
|
||||||
|
group would be deleted. This prevents the above example from deleting all
|
||||||
|
snapshots.
|
||||||
|
|
||||||
|
It is possible to temporarily disable the new check by setting the environment variable
|
||||||
|
`RESTIC_FEATURES=safe-forget-keep-tags=false`. Note that this feature flag
|
||||||
|
will be removed in the next minor restic version.
|
||||||
|
|
||||||
|
https://github.com/restic/restic/issues/4568
|
||||||
|
https://github.com/restic/restic/pull/4764
|
||||||
|
https://forum.restic.net/t/delete-all-snapshots-in-one-command-is-this-feature-intentional/6923/3
|
8
changelog/unreleased/pull-4764
Normal file
8
changelog/unreleased/pull-4764
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
Enhancement: Remove all snapshots using `forget --unsafe-allow-remove-all`
|
||||||
|
|
||||||
|
The forget command now supports the `--unsafe-allow-remove-all` option. It must
|
||||||
|
always be combined with a snapshot filter (by host, path or tag).
|
||||||
|
For example the command `forget --tag example --unsafe-allow-remove-all`,
|
||||||
|
removes all snapshots with tag `example`.
|
||||||
|
|
||||||
|
https://github.com/restic/restic/pull/4764
|
|
@ -3,10 +3,12 @@ package main
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/restic/restic/internal/errors"
|
"github.com/restic/restic/internal/errors"
|
||||||
|
"github.com/restic/restic/internal/feature"
|
||||||
"github.com/restic/restic/internal/restic"
|
"github.com/restic/restic/internal/restic"
|
||||||
"github.com/restic/restic/internal/ui/termstatus"
|
"github.com/restic/restic/internal/ui/termstatus"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
@ -91,6 +93,8 @@ type ForgetOptions struct {
|
||||||
WithinYearly restic.Duration
|
WithinYearly restic.Duration
|
||||||
KeepTags restic.TagLists
|
KeepTags restic.TagLists
|
||||||
|
|
||||||
|
UnsafeAllowRemoveAll bool
|
||||||
|
|
||||||
restic.SnapshotFilter
|
restic.SnapshotFilter
|
||||||
Compact bool
|
Compact bool
|
||||||
|
|
||||||
|
@ -120,6 +124,7 @@ func init() {
|
||||||
f.VarP(&forgetOptions.WithinMonthly, "keep-within-monthly", "", "keep monthly snapshots that are newer than `duration` (eg. 1y5m7d2h) relative to the latest snapshot")
|
f.VarP(&forgetOptions.WithinMonthly, "keep-within-monthly", "", "keep monthly snapshots that are newer than `duration` (eg. 1y5m7d2h) relative to the latest snapshot")
|
||||||
f.VarP(&forgetOptions.WithinYearly, "keep-within-yearly", "", "keep yearly snapshots that are newer than `duration` (eg. 1y5m7d2h) relative to the latest snapshot")
|
f.VarP(&forgetOptions.WithinYearly, "keep-within-yearly", "", "keep yearly 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.Var(&forgetOptions.KeepTags, "keep-tag", "keep snapshots with this `taglist` (can be specified multiple times)")
|
||||||
|
f.BoolVar(&forgetOptions.UnsafeAllowRemoveAll, "unsafe-allow-remove-all", false, "allow deleting all snapshots of a snapshot group")
|
||||||
|
|
||||||
initMultiSnapshotFilter(f, &forgetOptions.SnapshotFilter, false)
|
initMultiSnapshotFilter(f, &forgetOptions.SnapshotFilter, false)
|
||||||
f.StringArrayVar(&forgetOptions.Hosts, "hostname", nil, "only consider snapshots with the given `hostname` (can be specified multiple times)")
|
f.StringArrayVar(&forgetOptions.Hosts, "hostname", nil, "only consider snapshots with the given `hostname` (can be specified multiple times)")
|
||||||
|
@ -221,54 +226,62 @@ func runForget(ctx context.Context, opts ForgetOptions, pruneOptions PruneOption
|
||||||
Tags: opts.KeepTags,
|
Tags: opts.KeepTags,
|
||||||
}
|
}
|
||||||
|
|
||||||
if policy.Empty() && len(args) == 0 {
|
if policy.Empty() {
|
||||||
printer.P("no policy was specified, no snapshots will be removed\n")
|
if opts.UnsafeAllowRemoveAll {
|
||||||
|
if opts.SnapshotFilter.Empty() {
|
||||||
|
return errors.Fatal("--unsafe-allow-remove-all is not allowed unless a snapshot filter option is specified")
|
||||||
|
}
|
||||||
|
// UnsafeAllowRemoveAll together with snapshot filter is fine
|
||||||
|
} else {
|
||||||
|
return errors.Fatal("no policy was specified, no snapshots will be removed")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !policy.Empty() {
|
printer.P("Applying Policy: %v\n", policy)
|
||||||
printer.P("Applying Policy: %v\n", policy)
|
|
||||||
|
|
||||||
for k, snapshotGroup := range snapshotGroups {
|
for k, snapshotGroup := range snapshotGroups {
|
||||||
if gopts.Verbose >= 1 && !gopts.JSON {
|
if gopts.Verbose >= 1 && !gopts.JSON {
|
||||||
err = PrintSnapshotGroupHeader(globalOptions.stdout, k)
|
err = PrintSnapshotGroupHeader(globalOptions.stdout, k)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var key restic.SnapshotGroupKey
|
|
||||||
if json.Unmarshal([]byte(k), &key) != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var fg ForgetGroup
|
var key restic.SnapshotGroupKey
|
||||||
fg.Tags = key.Tags
|
if json.Unmarshal([]byte(k), &key) != nil {
|
||||||
fg.Host = key.Hostname
|
return err
|
||||||
fg.Paths = key.Paths
|
}
|
||||||
|
|
||||||
keep, remove, reasons := restic.ApplyPolicy(snapshotGroup, policy)
|
var fg ForgetGroup
|
||||||
|
fg.Tags = key.Tags
|
||||||
|
fg.Host = key.Hostname
|
||||||
|
fg.Paths = key.Paths
|
||||||
|
|
||||||
if len(keep) != 0 && !gopts.Quiet && !gopts.JSON {
|
keep, remove, reasons := restic.ApplyPolicy(snapshotGroup, policy)
|
||||||
printer.P("keep %d snapshots:\n", len(keep))
|
|
||||||
PrintSnapshots(globalOptions.stdout, keep, reasons, opts.Compact)
|
|
||||||
printer.P("\n")
|
|
||||||
}
|
|
||||||
fg.Keep = asJSONSnapshots(keep)
|
|
||||||
|
|
||||||
if len(remove) != 0 && !gopts.Quiet && !gopts.JSON {
|
if feature.Flag.Enabled(feature.SafeForgetKeepTags) && !policy.Empty() && len(keep) == 0 {
|
||||||
printer.P("remove %d snapshots:\n", len(remove))
|
return fmt.Errorf("refusing to delete last snapshot of snapshot group \"%v\"", key.String())
|
||||||
PrintSnapshots(globalOptions.stdout, remove, nil, opts.Compact)
|
}
|
||||||
printer.P("\n")
|
if len(keep) != 0 && !gopts.Quiet && !gopts.JSON {
|
||||||
}
|
printer.P("keep %d snapshots:\n", len(keep))
|
||||||
fg.Remove = asJSONSnapshots(remove)
|
PrintSnapshots(globalOptions.stdout, keep, reasons, opts.Compact)
|
||||||
|
printer.P("\n")
|
||||||
|
}
|
||||||
|
fg.Keep = asJSONSnapshots(keep)
|
||||||
|
|
||||||
fg.Reasons = asJSONKeeps(reasons)
|
if len(remove) != 0 && !gopts.Quiet && !gopts.JSON {
|
||||||
|
printer.P("remove %d snapshots:\n", len(remove))
|
||||||
|
PrintSnapshots(globalOptions.stdout, remove, nil, opts.Compact)
|
||||||
|
printer.P("\n")
|
||||||
|
}
|
||||||
|
fg.Remove = asJSONSnapshots(remove)
|
||||||
|
|
||||||
jsonGroups = append(jsonGroups, &fg)
|
fg.Reasons = asJSONKeeps(reasons)
|
||||||
|
|
||||||
for _, sn := range remove {
|
jsonGroups = append(jsonGroups, &fg)
|
||||||
removeSnIDs.Insert(*sn.ID())
|
|
||||||
}
|
for _, sn := range remove {
|
||||||
|
removeSnIDs.Insert(*sn.ID())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,18 +2,65 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/restic/restic/internal/restic"
|
||||||
rtest "github.com/restic/restic/internal/test"
|
rtest "github.com/restic/restic/internal/test"
|
||||||
"github.com/restic/restic/internal/ui/termstatus"
|
"github.com/restic/restic/internal/ui/termstatus"
|
||||||
)
|
)
|
||||||
|
|
||||||
func testRunForget(t testing.TB, gopts GlobalOptions, args ...string) {
|
func testRunForgetMayFail(gopts GlobalOptions, opts ForgetOptions, args ...string) error {
|
||||||
opts := ForgetOptions{}
|
|
||||||
pruneOpts := PruneOptions{
|
pruneOpts := PruneOptions{
|
||||||
MaxUnused: "5%",
|
MaxUnused: "5%",
|
||||||
}
|
}
|
||||||
rtest.OK(t, withTermStatus(gopts, func(ctx context.Context, term *termstatus.Terminal) error {
|
return withTermStatus(gopts, func(ctx context.Context, term *termstatus.Terminal) error {
|
||||||
return runForget(context.TODO(), opts, pruneOpts, gopts, term, args)
|
return runForget(context.TODO(), opts, pruneOpts, gopts, term, args)
|
||||||
}))
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testRunForget(t testing.TB, gopts GlobalOptions, opts ForgetOptions, args ...string) {
|
||||||
|
rtest.OK(t, testRunForgetMayFail(gopts, opts, args...))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRunForgetSafetyNet(t *testing.T) {
|
||||||
|
env, cleanup := withTestEnvironment(t)
|
||||||
|
defer cleanup()
|
||||||
|
|
||||||
|
testSetupBackupData(t, env)
|
||||||
|
|
||||||
|
opts := BackupOptions{
|
||||||
|
Host: "example",
|
||||||
|
}
|
||||||
|
testRunBackup(t, "", []string{filepath.Join(env.testdata, "0", "0", "9")}, opts, env.gopts)
|
||||||
|
testRunBackup(t, "", []string{filepath.Join(env.testdata, "0", "0", "9")}, opts, env.gopts)
|
||||||
|
testListSnapshots(t, env.gopts, 2)
|
||||||
|
|
||||||
|
// --keep-tags invalid
|
||||||
|
err := testRunForgetMayFail(env.gopts, ForgetOptions{
|
||||||
|
KeepTags: restic.TagLists{restic.TagList{"invalid"}},
|
||||||
|
GroupBy: restic.SnapshotGroupByOptions{Host: true, Path: true},
|
||||||
|
})
|
||||||
|
rtest.Assert(t, strings.Contains(err.Error(), `refusing to delete last snapshot of snapshot group "host example, path`), "wrong error message got %v", err)
|
||||||
|
|
||||||
|
// disallow `forget --unsafe-allow-remove-all`
|
||||||
|
err = testRunForgetMayFail(env.gopts, ForgetOptions{
|
||||||
|
UnsafeAllowRemoveAll: true,
|
||||||
|
})
|
||||||
|
rtest.Assert(t, strings.Contains(err.Error(), `--unsafe-allow-remove-all is not allowed unless a snapshot filter option is specified`), "wrong error message got %v", err)
|
||||||
|
|
||||||
|
// disallow `forget` without options
|
||||||
|
err = testRunForgetMayFail(env.gopts, ForgetOptions{})
|
||||||
|
rtest.Assert(t, strings.Contains(err.Error(), `no policy was specified, no snapshots will be removed`), "wrong error message got %v", err)
|
||||||
|
|
||||||
|
// `forget --host example --unsafe-allow-remmove-all` should work
|
||||||
|
testRunForget(t, env.gopts, ForgetOptions{
|
||||||
|
UnsafeAllowRemoveAll: true,
|
||||||
|
GroupBy: restic.SnapshotGroupByOptions{Host: true, Path: true},
|
||||||
|
SnapshotFilter: restic.SnapshotFilter{
|
||||||
|
Hosts: []string{opts.Host},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
testListSnapshots(t, env.gopts, 0)
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,7 +75,7 @@ func createPrunableRepo(t *testing.T, env *testEnvironment) {
|
||||||
testListSnapshots(t, env.gopts, 3)
|
testListSnapshots(t, env.gopts, 3)
|
||||||
|
|
||||||
testRunForgetJSON(t, env.gopts)
|
testRunForgetJSON(t, env.gopts)
|
||||||
testRunForget(t, env.gopts, firstSnapshot.String())
|
testRunForget(t, env.gopts, ForgetOptions{}, firstSnapshot.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func testRunForgetJSON(t testing.TB, gopts GlobalOptions, args ...string) {
|
func testRunForgetJSON(t testing.TB, gopts GlobalOptions, args ...string) {
|
||||||
|
@ -129,7 +129,7 @@ func TestPruneWithDamagedRepository(t *testing.T) {
|
||||||
// create and delete snapshot to create unused blobs
|
// create and delete snapshot to create unused blobs
|
||||||
testRunBackup(t, "", []string{filepath.Join(env.testdata, "0", "0", "9", "2")}, opts, env.gopts)
|
testRunBackup(t, "", []string{filepath.Join(env.testdata, "0", "0", "9", "2")}, opts, env.gopts)
|
||||||
firstSnapshot := testListSnapshots(t, env.gopts, 1)[0]
|
firstSnapshot := testListSnapshots(t, env.gopts, 1)[0]
|
||||||
testRunForget(t, env.gopts, firstSnapshot.String())
|
testRunForget(t, env.gopts, ForgetOptions{}, firstSnapshot.String())
|
||||||
|
|
||||||
oldPacks := listPacks(env.gopts, t)
|
oldPacks := listPacks(env.gopts, t)
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,7 @@ func TestRepairSnapshotsWithLostData(t *testing.T) {
|
||||||
testRunCheckMustFail(t, env.gopts)
|
testRunCheckMustFail(t, env.gopts)
|
||||||
|
|
||||||
// repository must be ok after removing the broken snapshots
|
// repository must be ok after removing the broken snapshots
|
||||||
testRunForget(t, env.gopts, snapshotIDs[0].String(), snapshotIDs[1].String())
|
testRunForget(t, env.gopts, ForgetOptions{}, snapshotIDs[0].String(), snapshotIDs[1].String())
|
||||||
testListSnapshots(t, env.gopts, 2)
|
testListSnapshots(t, env.gopts, 2)
|
||||||
_, err := testRunCheckOutput(env.gopts, false)
|
_, err := testRunCheckOutput(env.gopts, false)
|
||||||
rtest.OK(t, err)
|
rtest.OK(t, err)
|
||||||
|
@ -86,7 +86,7 @@ func TestRepairSnapshotsWithLostTree(t *testing.T) {
|
||||||
|
|
||||||
// remove tree for foo/bar and the now completely broken first snapshot
|
// remove tree for foo/bar and the now completely broken first snapshot
|
||||||
removePacks(env.gopts, t, restic.NewIDSet(oldPacks...))
|
removePacks(env.gopts, t, restic.NewIDSet(oldPacks...))
|
||||||
testRunForget(t, env.gopts, oldSnapshot[0].String())
|
testRunForget(t, env.gopts, ForgetOptions{}, oldSnapshot[0].String())
|
||||||
testRunCheckMustFail(t, env.gopts)
|
testRunCheckMustFail(t, env.gopts)
|
||||||
|
|
||||||
// repair
|
// repair
|
||||||
|
|
|
@ -182,7 +182,9 @@ The ``forget`` command accepts the following policy options:
|
||||||
- ``--keep-yearly n`` for the last ``n`` years which have one or more
|
- ``--keep-yearly n`` for the last ``n`` years which have one or more
|
||||||
snapshots, keep only the most recent one for each year.
|
snapshots, keep only the most recent one for each year.
|
||||||
- ``--keep-tag`` keep all snapshots which have all tags specified by
|
- ``--keep-tag`` keep all snapshots which have all tags specified by
|
||||||
this option (can be specified multiple times).
|
this option (can be specified multiple times). The ``forget`` command will
|
||||||
|
exit with an error if all snapshots in a snapshot group would be removed
|
||||||
|
as none of them have the specified tags.
|
||||||
- ``--keep-within duration`` keep all snapshots having a timestamp within
|
- ``--keep-within duration`` keep all snapshots having a timestamp within
|
||||||
the specified duration of the latest snapshot, where ``duration`` is a
|
the specified duration of the latest snapshot, where ``duration`` is a
|
||||||
number of years, months, days, and hours. E.g. ``2y5m7d3h`` will keep all
|
number of years, months, days, and hours. E.g. ``2y5m7d3h`` will keep all
|
||||||
|
@ -336,12 +338,23 @@ year and yearly for the last 75 years, you can instead specify ``forget
|
||||||
--keep-within-yearly 75y`` (note that `1w` is not a recognized duration, so
|
--keep-within-yearly 75y`` (note that `1w` is not a recognized duration, so
|
||||||
you will have to specify `7d` instead).
|
you will have to specify `7d` instead).
|
||||||
|
|
||||||
|
|
||||||
|
Removing all snapshots
|
||||||
|
======================
|
||||||
|
|
||||||
For safety reasons, restic refuses to act on an "empty" policy. For example,
|
For safety reasons, restic refuses to act on an "empty" policy. For example,
|
||||||
if one were to specify ``--keep-last 0`` to forget *all* snapshots in the
|
if one were to specify ``--keep-last 0`` to forget *all* snapshots in the
|
||||||
repository, restic will respond that no snapshots will be removed. To delete
|
repository, restic will respond that no snapshots will be removed. To delete
|
||||||
all snapshots, use ``--keep-last 1`` and then finally remove the last snapshot
|
all snapshots, use ``--keep-last 1`` and then finally remove the last snapshot
|
||||||
manually (by passing the ID to ``forget``).
|
manually (by passing the ID to ``forget``).
|
||||||
|
|
||||||
|
Since restic 0.17.0, it is possible to delete all snapshots for a specific
|
||||||
|
host, tag or path using the ``--unsafe-allow-remove-all`` option. The option
|
||||||
|
must always be combined with a snapshot filter (by host, path or tag).
|
||||||
|
For example the command ``forget --tag example --unsafe-allow-remove-all``
|
||||||
|
removes all snapshots with tag ``example``.
|
||||||
|
|
||||||
|
|
||||||
Security considerations in append-only mode
|
Security considerations in append-only mode
|
||||||
===========================================
|
===========================================
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ const (
|
||||||
DeprecateLegacyIndex FlagName = "deprecate-legacy-index"
|
DeprecateLegacyIndex FlagName = "deprecate-legacy-index"
|
||||||
DeprecateS3LegacyLayout FlagName = "deprecate-s3-legacy-layout"
|
DeprecateS3LegacyLayout FlagName = "deprecate-s3-legacy-layout"
|
||||||
DeviceIDForHardlinks FlagName = "device-id-for-hardlinks"
|
DeviceIDForHardlinks FlagName = "device-id-for-hardlinks"
|
||||||
|
SafeForgetKeepTags FlagName = "safe-forget-keep-tags"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -17,5 +18,6 @@ func init() {
|
||||||
DeprecateLegacyIndex: {Type: Beta, Description: "disable support for index format used by restic 0.1.0. Use `restic repair index` to update the index if necessary."},
|
DeprecateLegacyIndex: {Type: Beta, Description: "disable support for index format used by restic 0.1.0. Use `restic repair index` to update the index if necessary."},
|
||||||
DeprecateS3LegacyLayout: {Type: Beta, Description: "disable support for S3 legacy layout used up to restic 0.7.0. Use `RESTIC_FEATURES=deprecate-s3-legacy-layout=false restic migrate s3_layout` to migrate your S3 repository if necessary."},
|
DeprecateS3LegacyLayout: {Type: Beta, Description: "disable support for S3 legacy layout used up to restic 0.7.0. Use `RESTIC_FEATURES=deprecate-s3-legacy-layout=false restic migrate s3_layout` to migrate your S3 repository if necessary."},
|
||||||
DeviceIDForHardlinks: {Type: Alpha, Description: "store deviceID only for hardlinks to reduce metadata changes for example when using btrfs subvolumes. Will be removed in a future restic version after repository format 3 is available"},
|
DeviceIDForHardlinks: {Type: Alpha, Description: "store deviceID only for hardlinks to reduce metadata changes for example when using btrfs subvolumes. Will be removed in a future restic version after repository format 3 is available"},
|
||||||
|
SafeForgetKeepTags: {Type: Beta, Description: "prevent deleting all snapshots if the tag passed to `forget --keep-tags tagname` does not exist"},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ type SnapshotFilter struct {
|
||||||
TimestampLimit time.Time
|
TimestampLimit time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *SnapshotFilter) empty() bool {
|
func (f *SnapshotFilter) Empty() bool {
|
||||||
return len(f.Hosts)+len(f.Tags)+len(f.Paths) == 0
|
return len(f.Hosts)+len(f.Tags)+len(f.Paths) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,7 +173,7 @@ func (f *SnapshotFilter) FindAll(ctx context.Context, be Lister, loader LoaderUn
|
||||||
}
|
}
|
||||||
|
|
||||||
// Give the user some indication their filters are not used.
|
// Give the user some indication their filters are not used.
|
||||||
if !usedFilter && !f.empty() {
|
if !usedFilter && !f.Empty() {
|
||||||
return fn("filters", nil, errors.Errorf("explicit snapshot ids are given"))
|
return fn("filters", nil, errors.Errorf("explicit snapshot ids are given"))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -66,6 +66,20 @@ type SnapshotGroupKey struct {
|
||||||
Tags []string `json:"tags"`
|
Tags []string `json:"tags"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *SnapshotGroupKey) String() string {
|
||||||
|
var parts []string
|
||||||
|
if s.Hostname != "" {
|
||||||
|
parts = append(parts, fmt.Sprintf("host %v", s.Hostname))
|
||||||
|
}
|
||||||
|
if len(s.Paths) != 0 {
|
||||||
|
parts = append(parts, fmt.Sprintf("path %v", s.Paths))
|
||||||
|
}
|
||||||
|
if len(s.Tags) != 0 {
|
||||||
|
parts = append(parts, fmt.Sprintf("tags %v", s.Tags))
|
||||||
|
}
|
||||||
|
return strings.Join(parts, ", ")
|
||||||
|
}
|
||||||
|
|
||||||
// GroupSnapshots takes a list of snapshots and a grouping criteria and creates
|
// GroupSnapshots takes a list of snapshots and a grouping criteria and creates
|
||||||
// a grouped list of snapshots.
|
// a grouped list of snapshots.
|
||||||
func GroupSnapshots(snapshots Snapshots, groupBy SnapshotGroupByOptions) (map[string]Snapshots, bool, error) {
|
func GroupSnapshots(snapshots Snapshots, groupBy SnapshotGroupByOptions) (map[string]Snapshots, bool, error) {
|
||||||
|
|
|
@ -94,7 +94,11 @@ func (e ExpirePolicy) String() (s string) {
|
||||||
s += fmt.Sprintf("all snapshots within %s of the newest", e.Within)
|
s += fmt.Sprintf("all snapshots within %s of the newest", e.Within)
|
||||||
}
|
}
|
||||||
|
|
||||||
s = "keep " + s
|
if s == "" {
|
||||||
|
s = "remove"
|
||||||
|
} else {
|
||||||
|
s = "keep " + s
|
||||||
|
}
|
||||||
|
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
@ -186,16 +190,6 @@ func ApplyPolicy(list Snapshots, p ExpirePolicy) (keep, remove Snapshots, reason
|
||||||
// sort newest snapshots first
|
// sort newest snapshots first
|
||||||
sort.Stable(list)
|
sort.Stable(list)
|
||||||
|
|
||||||
if p.Empty() {
|
|
||||||
for _, sn := range list {
|
|
||||||
reasons = append(reasons, KeepReason{
|
|
||||||
Snapshot: sn,
|
|
||||||
Matches: []string{"policy is empty"},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return list, remove, reasons
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(list) == 0 {
|
if len(list) == 0 {
|
||||||
return list, nil, nil
|
return list, nil, nil
|
||||||
}
|
}
|
||||||
|
|
1781
internal/restic/testdata/policy_keep_snapshots_0
vendored
1781
internal/restic/testdata/policy_keep_snapshots_0
vendored
File diff suppressed because it is too large
Load diff
412
internal/restic/testdata/policy_keep_snapshots_36
vendored
412
internal/restic/testdata/policy_keep_snapshots_36
vendored
File diff suppressed because it is too large
Load diff
515
internal/restic/testdata/policy_keep_snapshots_37
vendored
515
internal/restic/testdata/policy_keep_snapshots_37
vendored
File diff suppressed because it is too large
Load diff
362
internal/restic/testdata/policy_keep_snapshots_38
vendored
362
internal/restic/testdata/policy_keep_snapshots_38
vendored
|
@ -507,7 +507,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -518,7 +520,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -529,7 +533,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -540,7 +546,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -551,7 +559,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -562,7 +572,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -573,7 +585,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -584,7 +598,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -595,7 +611,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -606,7 +624,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -617,7 +637,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -628,7 +650,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -639,7 +663,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -650,7 +676,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -661,7 +689,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -672,7 +702,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -683,7 +715,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -694,7 +728,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -705,7 +741,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -716,7 +754,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -727,7 +767,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -738,7 +780,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -749,7 +793,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -760,7 +806,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -771,7 +819,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -782,7 +832,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -793,7 +845,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -804,7 +858,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -815,7 +871,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -826,7 +884,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -837,7 +897,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -848,7 +910,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -859,7 +923,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -870,7 +936,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -881,7 +949,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -892,7 +962,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -903,7 +975,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -914,7 +988,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -925,7 +1001,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -936,7 +1014,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -947,7 +1027,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -958,7 +1040,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -969,7 +1053,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -980,7 +1066,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -991,7 +1079,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1002,7 +1092,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1013,7 +1105,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1024,7 +1118,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1035,7 +1131,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1046,7 +1144,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1057,7 +1157,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1068,7 +1170,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1079,7 +1183,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1090,7 +1196,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1101,7 +1209,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1112,7 +1222,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1127,7 +1239,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1141,7 +1255,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1155,7 +1271,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1169,7 +1287,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1183,7 +1303,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1197,7 +1319,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1211,7 +1335,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1225,7 +1351,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1239,7 +1367,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1253,7 +1383,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1267,7 +1399,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1281,7 +1415,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1295,7 +1431,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1309,7 +1447,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1323,7 +1463,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1334,7 +1476,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1345,7 +1489,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1356,7 +1502,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1367,7 +1515,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1378,7 +1528,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1389,7 +1541,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1400,7 +1554,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1411,7 +1567,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1422,7 +1580,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1433,7 +1593,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1444,7 +1606,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1455,7 +1619,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1466,7 +1632,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1477,7 +1645,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1488,7 +1658,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1499,7 +1671,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1510,7 +1684,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1521,7 +1697,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -1532,7 +1710,9 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"hourly snapshot"
|
"hourly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Hourly": -1}
|
"counters": {
|
||||||
|
"hourly": -1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -74,10 +74,15 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"daily snapshot",
|
"daily snapshot",
|
||||||
"weekly snapshot",
|
"weekly snapshot",
|
||||||
"monthly snapshot",
|
"monthly snapshot",
|
||||||
"yearly snapshot"
|
"yearly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Daily": 2, "Weekly": 1, "Monthly": -1, "Yearly": -1}
|
"counters": {
|
||||||
|
"daily": 2,
|
||||||
|
"weekly": 1,
|
||||||
|
"monthly": -1,
|
||||||
|
"yearly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -89,7 +94,11 @@
|
||||||
"daily snapshot",
|
"daily snapshot",
|
||||||
"weekly snapshot"
|
"weekly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Daily": 1, "Monthly": -1, "Yearly": -1}
|
"counters": {
|
||||||
|
"daily": 1,
|
||||||
|
"monthly": -1,
|
||||||
|
"yearly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -100,7 +109,10 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"daily snapshot"
|
"daily snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Monthly": -1, "Yearly": -1}
|
"counters": {
|
||||||
|
"monthly": -1,
|
||||||
|
"yearly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -112,7 +124,10 @@
|
||||||
"monthly snapshot",
|
"monthly snapshot",
|
||||||
"yearly snapshot"
|
"yearly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Monthly": -1, "Yearly": -1}
|
"counters": {
|
||||||
|
"monthly": -1,
|
||||||
|
"yearly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -123,7 +138,10 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"monthly snapshot"
|
"monthly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Monthly": -1, "Yearly": -1}
|
"counters": {
|
||||||
|
"monthly": -1,
|
||||||
|
"yearly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -134,7 +152,10 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"monthly snapshot"
|
"monthly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Monthly": -1, "Yearly": -1}
|
"counters": {
|
||||||
|
"monthly": -1,
|
||||||
|
"yearly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -145,7 +166,10 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"monthly snapshot"
|
"monthly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Monthly": -1, "Yearly": -1}
|
"counters": {
|
||||||
|
"monthly": -1,
|
||||||
|
"yearly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -157,7 +181,10 @@
|
||||||
"monthly snapshot",
|
"monthly snapshot",
|
||||||
"yearly snapshot"
|
"yearly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Monthly": -1, "Yearly": -1}
|
"counters": {
|
||||||
|
"monthly": -1,
|
||||||
|
"yearly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -171,7 +198,10 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"monthly snapshot"
|
"monthly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Monthly": -1, "Yearly": -1}
|
"counters": {
|
||||||
|
"monthly": -1,
|
||||||
|
"yearly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -182,7 +212,10 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"monthly snapshot"
|
"monthly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Monthly": -1, "Yearly": -1}
|
"counters": {
|
||||||
|
"monthly": -1,
|
||||||
|
"yearly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -193,7 +226,10 @@
|
||||||
"matches": [
|
"matches": [
|
||||||
"monthly snapshot"
|
"monthly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Monthly": -1, "Yearly": -1}
|
"counters": {
|
||||||
|
"monthly": -1,
|
||||||
|
"yearly": -1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"snapshot": {
|
"snapshot": {
|
||||||
|
@ -205,7 +241,10 @@
|
||||||
"monthly snapshot",
|
"monthly snapshot",
|
||||||
"yearly snapshot"
|
"yearly snapshot"
|
||||||
],
|
],
|
||||||
"counters": {"Monthly": -1, "Yearly": -1}
|
"counters": {
|
||||||
|
"monthly": -1,
|
||||||
|
"yearly": -1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
Loading…
Reference in a new issue