mirror of
https://github.com/zrepl/zrepl.git
synced 2024-11-22 08:23:50 +01:00
cmd: automatic inverting of DatasetMapFilter
This commit is contained in:
parent
1deaa459c8
commit
e2149de840
@ -4,8 +4,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/zrepl/zrepl/zfs"
|
|
||||||
"github.com/mitchellh/mapstructure"
|
"github.com/mitchellh/mapstructure"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/zrepl/zrepl/zfs"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DatasetMapFilter struct {
|
type DatasetMapFilter struct {
|
||||||
@ -144,14 +145,46 @@ func (m DatasetMapFilter) Filter(p *zfs.DatasetPath) (pass bool, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Construct a new filter-only DatasetMapFilter from a mapping
|
||||||
|
// The new filter allows excactly those paths that were not forbidden by the mapping.
|
||||||
|
func (m DatasetMapFilter) InvertedFilter() (inv *DatasetMapFilter, err error) {
|
||||||
|
|
||||||
|
if m.filterOnly {
|
||||||
|
err = errors.Errorf("can only invert mappings")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
inv = &DatasetMapFilter{
|
||||||
|
make([]datasetMapFilterEntry, len(m.entries)),
|
||||||
|
true,
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, e := range m.entries {
|
||||||
|
inv.entries[i].path, err = zfs.NewDatasetPath(e.mapping)
|
||||||
|
if err != nil {
|
||||||
|
err = errors.Wrapf(err, "mapping cannot be inverted: '%s' is not a dataset path: %s", e.mapping)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
inv.entries[i].mapping = MapFilterResultOk
|
||||||
|
inv.entries[i].subtreeMatch = e.subtreeMatch
|
||||||
|
}
|
||||||
|
|
||||||
|
return inv, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
MapFilterResultOk string = "ok"
|
||||||
|
MapFilterResultOmit string = "omit"
|
||||||
|
)
|
||||||
|
|
||||||
// Parse a dataset filter result
|
// Parse a dataset filter result
|
||||||
func parseDatasetFilterResult(result string) (pass bool, err error) {
|
func parseDatasetFilterResult(result string) (pass bool, err error) {
|
||||||
l := strings.ToLower(result)
|
l := strings.ToLower(result)
|
||||||
switch strings.ToLower(l) {
|
switch strings.ToLower(l) {
|
||||||
case "ok":
|
case MapFilterResultOk:
|
||||||
pass = true
|
pass = true
|
||||||
return
|
return
|
||||||
case "omit":
|
case MapFilterResultOmit:
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
err = fmt.Errorf("'%s' is not a valid filter result", result)
|
err = fmt.Errorf("'%s' is not a valid filter result", result)
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/kr/pretty"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/zrepl/zrepl/util"
|
"github.com/zrepl/zrepl/util"
|
||||||
"github.com/zrepl/zrepl/zfs"
|
"github.com/zrepl/zrepl/zfs"
|
||||||
@ -135,3 +136,36 @@ func TestDatasetMapFilter(t *testing.T) {
|
|||||||
expectFilter(filter2, "foo", false) // default to omit
|
expectFilter(filter2, "foo", false) // default to omit
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDatasetMapFilter_InvertedFilter(t *testing.T) {
|
||||||
|
mapspec := map[string]string{
|
||||||
|
"a/b": "1/2",
|
||||||
|
"a/b/c<": "3",
|
||||||
|
"a/b/c/d<": "1/2/a",
|
||||||
|
}
|
||||||
|
|
||||||
|
m, err := parseDatasetMapFilter(mapspec, false)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
inv, err := m.InvertedFilter()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
t.Log(pretty.Sprint(inv))
|
||||||
|
|
||||||
|
expectMapping := func(m *DatasetMapFilter, ps string, expRes bool) {
|
||||||
|
p, err := zfs.NewDatasetPath(ps)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
r, err := m.Filter(p)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, expRes, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
expectMapping(inv, "4", false)
|
||||||
|
expectMapping(inv, "3", true)
|
||||||
|
expectMapping(inv, "3/x", true)
|
||||||
|
expectMapping(inv, "1", false)
|
||||||
|
expectMapping(inv, "1/2", true)
|
||||||
|
expectMapping(inv, "1/2/3", false)
|
||||||
|
expectMapping(inv, "1/2/a/b", true)
|
||||||
|
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user