Skip to content

Commit 71ac548

Browse files
authored
PBM-1465: Selective backup/restore for sharded collections fails for setups with config shards (#1078)
Fixes for: * selective backup didn't dump non-config namespaces on Config Shard RS * during the restore procedure, oplog replay step didn't apply entries for non-config namespace on Config Shard RS
1 parent c683a20 commit 71ac548

File tree

3 files changed

+112
-0
lines changed

3 files changed

+112
-0
lines changed

pbm/backup/logical.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,11 @@ func makeConfigsvrDocFilter(nss []string, selector util.ChunkSelector) archive.D
379379
return selector.Selected(doc)
380380
}
381381

382+
// Config Shard should keep non-config collections
383+
if selectedNS(ns) {
384+
return true
385+
}
386+
382387
return false
383388
}
384389
}

pbm/backup/logical_test.go

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package backup
2+
3+
import (
4+
"testing"
5+
6+
"go.mongodb.org/mongo-driver/bson"
7+
8+
"github.com/percona/percona-backup-mongodb/pbm/util"
9+
)
10+
11+
func TestMakeConfigsvrDocFilter(t *testing.T) {
12+
t.Run("selective backup without wildcards", func(t *testing.T) {
13+
testCases := []struct {
14+
desc string
15+
bcpNS []string
16+
docNS string
17+
selected bool
18+
}{
19+
{
20+
desc: "single backup ns, doc selected",
21+
bcpNS: []string{"d.c"},
22+
docNS: "d.c",
23+
selected: true,
24+
},
25+
{
26+
desc: "multiple backup ns, doc selected",
27+
bcpNS: []string{"d.c1", "d.c2", "d.c3"},
28+
docNS: "d.c2",
29+
selected: true,
30+
},
31+
{
32+
desc: "single backup ns, doc not selected",
33+
bcpNS: []string{"d.c"},
34+
docNS: "x.y",
35+
selected: false,
36+
},
37+
{
38+
desc: "single backup ns, doc not selected different coll",
39+
bcpNS: []string{"d.c"},
40+
docNS: "d.y",
41+
selected: false,
42+
},
43+
{
44+
desc: "multiple backup ns, doc not selected",
45+
bcpNS: []string{"d.c1", "d.c2", "d.c3"},
46+
docNS: "d.c4",
47+
selected: false,
48+
},
49+
}
50+
for _, tC := range testCases {
51+
t.Run(tC.desc, func(t *testing.T) {
52+
docFilter := makeConfigsvrDocFilter(tC.bcpNS, util.NewUUIDChunkSelector())
53+
res := docFilter(tC.docNS, bson.Raw{})
54+
if res != tC.selected {
55+
t.Errorf("want=%t, got=%t, for backup ns: %s and doc ns: %s", tC.selected, res, tC.bcpNS, tC.docNS)
56+
}
57+
})
58+
}
59+
})
60+
61+
t.Run("selective backup with wildcards", func(t *testing.T) {
62+
testCases := []struct {
63+
desc string
64+
bcpNS []string
65+
docNS string
66+
selected bool
67+
}{
68+
{
69+
desc: "single backup ns, doc selected",
70+
bcpNS: []string{"d.*"},
71+
docNS: "d.c",
72+
selected: true,
73+
},
74+
{
75+
desc: "multiple backup ns, doc selected",
76+
bcpNS: []string{"d1.*", "d2.*", "d3.*"},
77+
docNS: "d2.c2",
78+
selected: true,
79+
},
80+
{
81+
desc: "single backup ns, doc not selected",
82+
bcpNS: []string{"d.*"},
83+
docNS: "x.y",
84+
selected: false,
85+
},
86+
{
87+
desc: "multiple backup ns, doc not selected",
88+
bcpNS: []string{"d1.*", "d2.*", "d3.*"},
89+
docNS: "d4.c4",
90+
selected: false,
91+
},
92+
}
93+
for _, tC := range testCases {
94+
t.Run(tC.desc, func(t *testing.T) {
95+
docFilter := makeConfigsvrDocFilter(tC.bcpNS, util.NewUUIDChunkSelector())
96+
res := docFilter(tC.docNS, bson.Raw{})
97+
if res != tC.selected {
98+
t.Errorf("want=%t, got=%t, for backup ns: %s and doc ns: %s", tC.selected, res, tC.bcpNS, tC.docNS)
99+
}
100+
})
101+
}
102+
})
103+
}

pbm/restore/logical.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,9 @@ func newConfigsvrOpFilter(nss []string) oplog.OpFilter {
294294
selected := util.MakeSelectedPred(nss)
295295

296296
return func(r *oplog.Record) bool {
297+
if selected(r.Namespace) {
298+
return true
299+
}
297300
if r.Namespace != "config.databases" {
298301
return false
299302
}
@@ -436,6 +439,7 @@ func (r *Restore) PITR(
436439
}
437440
if r.nodeInfo.IsConfigSrv() && util.IsSelective(nss) {
438441
oplogOption.nss = []string{"config.databases"}
442+
oplogOption.nss = append(oplogOption.nss, nss...)
439443
oplogOption.filter = newConfigsvrOpFilter(nss)
440444
}
441445
err = r.applyOplog(ctx, oplogRanges, &oplogOption)

0 commit comments

Comments
 (0)