Skip to content

Commit 0b0766c

Browse files
committed
add more flexible snapshot match by regular expression
1 parent 8e3187d commit 0b0766c

File tree

4 files changed

+44
-1
lines changed

4 files changed

+44
-1
lines changed

backup/backup.go

+24-1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import (
3131
"io/ioutil"
3232
"os"
3333
"path/filepath"
34+
"regexp"
3435
"sort"
3536
"strings"
3637
"sync"
@@ -54,18 +55,35 @@ var (
5455
manifestmutex sync.Mutex
5556
)
5657

58+
type snapshotFilter struct {
59+
prefix string
60+
regexpMatch *regexp.Regexp
61+
}
62+
63+
func newSnapshotFilter(prefix string, match string) *snapshotFilter {
64+
filter := &snapshotFilter{
65+
prefix: prefix,
66+
}
67+
if match != "" {
68+
filter.regexpMatch = regexp.MustCompile(match)
69+
}
70+
log.AppLogger.Debugf("Filtering snapshots with prefix = %s, regex matcher = %v", filter.prefix, filter.regexpMatch)
71+
return filter
72+
}
73+
5774
// ProcessSmartOptions will compute the snapshots to use
5875
// nolint:funlen,gocyclo // Difficult to break this up
5976
func ProcessSmartOptions(ctx context.Context, jobInfo *files.JobInfo) error {
6077
snapshots, err := zfs.GetSnapshotsAndBookmarks(context.Background(), jobInfo.VolumeName)
6178
if err != nil {
6279
return err
6380
}
81+
filter := newSnapshotFilter(jobInfo.SnapshotPrefix, jobInfo.SnapshotRegexp)
6482
// Base Snapshots cannot be a bookmark
6583
for i := range snapshots {
6684
log.AppLogger.Debugf("Considering snapshot %s", snapshots[i].Name)
6785
if !snapshots[i].Bookmark {
68-
if jobInfo.SnapshotPrefix == "" || strings.HasPrefix(snapshots[i].Name, jobInfo.SnapshotPrefix) {
86+
if includeSnapshot(&snapshots[i], filter) {
6987
log.AppLogger.Debugf("Matched snapshot: %s", snapshots[i].Name)
7088
jobInfo.BaseSnapshot = snapshots[i]
7189
break
@@ -163,6 +181,11 @@ func ProcessSmartOptions(ctx context.Context, jobInfo *files.JobInfo) error {
163181
return nil
164182
}
165183

184+
func includeSnapshot(snapshot *files.SnapshotInfo, filter *snapshotFilter) bool {
185+
return (filter.prefix == "" || strings.HasPrefix(snapshot.Name, filter.prefix)) &&
186+
(filter.regexpMatch == nil || filter.regexpMatch.MatchString(snapshot.Name))
187+
}
188+
166189
// Will list all backups found in the target destination
167190
func getBackupsForTarget(ctx context.Context, volume, target string, jobInfo *files.JobInfo) ([]*files.JobInfo, error) {
168191
// Prepare the backend client

backup/backup_test.go

+13
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,19 @@ type errTestFunc func(error) bool
6565

6666
func nilErrTest(e error) bool { return e == nil }
6767

68+
func TestIncludeSnapshot(t *testing.T) {
69+
filter := newSnapshotFilter("", "^weekly.*")
70+
71+
snapInfo := &files.SnapshotInfo{Name: "hourly123"}
72+
if includeSnapshot(snapInfo, filter) {
73+
t.Errorf("%s incorrectly included", snapInfo.Name)
74+
}
75+
snapInfo.Name = "weekly456"
76+
if !includeSnapshot(snapInfo, filter) {
77+
t.Errorf("%s incorrectly excluded", snapInfo.Name)
78+
}
79+
}
80+
6881
func TestRetryUploadChainer(t *testing.T) {
6982
_, goodVol, badVol, err := prepareTestVols()
7083
if err != nil {

cmd/send.go

+6
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,12 @@ func init() {
117117
"",
118118
"Only consider snapshots starting with the given snapshot prefix",
119119
)
120+
sendCmd.Flags().StringVar(
121+
&jobInfo.SnapshotRegexp,
122+
"snapshotRegexp",
123+
"",
124+
"Only consider snapshots matching given regex",
125+
)
120126
sendCmd.Flags().DurationVar(
121127
&jobInfo.FullIfOlderThan,
122128
"fullIfOlderThan",

files/jobinfo.go

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ type JobInfo struct {
4545
BaseSnapshot SnapshotInfo
4646
IncrementalSnapshot SnapshotInfo
4747
SnapshotPrefix string
48+
SnapshotRegexp string
4849
Compressor string
4950
CompressionLevel int
5051
Separator string

0 commit comments

Comments
 (0)