@@ -64,6 +64,9 @@ type Restore struct {
64
64
indexCatalog * idx.IndexCatalog
65
65
}
66
66
67
+ // PBM restore from temp collections (pbmRUsers/pbmRRoles)should be used
68
+ type restoreUsersAndRolesOption bool
69
+
67
70
// New creates a new restore object
68
71
func New (leadConn connect.Client , nodeConn * mongo.Client , brief topo.NodeBrief , rsMap map [string ]string ) * Restore {
69
72
if rsMap == nil {
@@ -100,6 +103,41 @@ func (r *Restore) exit(ctx context.Context, err error) {
100
103
r .Close ()
101
104
}
102
105
106
+ // resolveNamespace resolves final namespace(s) based on the backup namespace,
107
+ // restore namespace, and option whether we should restore users&roles
108
+ func resolveNamespace (nssBackup , nssRestore []string , usingUsersAndRoles bool ) []string {
109
+ if util .IsSelective (nssRestore ) {
110
+ if usingUsersAndRoles {
111
+ var nss []string
112
+ nss = append (nss , nssRestore ... )
113
+ nss = append (nss ,
114
+ defs .DB + "." + defs .TmpUsersCollection ,
115
+ defs .DB + "." + defs .TmpRolesCollection ,
116
+ )
117
+ return nss
118
+ }
119
+
120
+ return nssRestore
121
+ }
122
+ if util .IsSelective (nssBackup ) {
123
+ return nssBackup
124
+ }
125
+
126
+ return nssBackup
127
+ }
128
+
129
+ // shouldRestoreUsersAndRoles determines whether user&roles should be restored from the backup
130
+ func shouldRestoreUsersAndRoles (nssBackup , nssRestore []string , usingUsersAndRoles bool ) restoreUsersAndRolesOption {
131
+ if util .IsSelective (nssBackup ) {
132
+ return false
133
+ }
134
+ if util .IsSelective (nssRestore ) {
135
+ return restoreUsersAndRolesOption (usingUsersAndRoles )
136
+ }
137
+
138
+ return true
139
+ }
140
+
103
141
// Snapshot do the snapshot's (mongo dump) restore
104
142
//
105
143
//nolint:nonamedreturns
@@ -116,10 +154,8 @@ func (r *Restore) Snapshot(ctx context.Context, cmd *ctrl.RestoreCmd, opid ctrl.
116
154
return err
117
155
}
118
156
119
- nss := cmd .Namespaces
120
- if ! util .IsSelective (nss ) {
121
- nss = bcp .Namespaces
122
- }
157
+ nss := resolveNamespace (bcp .Namespaces , cmd .Namespaces , cmd .UsersAndRoles )
158
+ usersAndRolesOpt := shouldRestoreUsersAndRoles (bcp .Namespaces , cmd .Namespaces , cmd .UsersAndRoles )
123
159
124
160
err = setRestoreBackup (ctx , r .leadConn , r .name , cmd .BackupName , nss )
125
161
if err != nil {
@@ -150,7 +186,7 @@ func (r *Restore) Snapshot(ctx context.Context, cmd *ctrl.RestoreCmd, opid ctrl.
150
186
return err
151
187
}
152
188
153
- err = r .RunSnapshot (ctx , dump , bcp , nss )
189
+ err = r .RunSnapshot (ctx , dump , bcp , nss , usersAndRolesOpt )
154
190
if err != nil {
155
191
return err
156
192
}
@@ -226,10 +262,8 @@ func (r *Restore) PITR(ctx context.Context, cmd *ctrl.RestoreCmd, opid ctrl.OPID
226
262
"Try to set an earlier snapshot. Or leave the snapshot empty so PBM will choose one." )
227
263
}
228
264
229
- nss := cmd .Namespaces
230
- if len (nss ) == 0 {
231
- nss = bcp .Namespaces
232
- }
265
+ nss := resolveNamespace (bcp .Namespaces , cmd .Namespaces , cmd .UsersAndRoles )
266
+ usersAndRolesOpt := shouldRestoreUsersAndRoles (bcp .Namespaces , cmd .Namespaces , cmd .UsersAndRoles )
233
267
234
268
if r .nodeInfo .IsLeader () {
235
269
err = SetOplogTimestamps (ctx , r .leadConn , r .name , 0 , int64 (cmd .OplogTS .T ))
@@ -281,7 +315,7 @@ func (r *Restore) PITR(ctx context.Context, cmd *ctrl.RestoreCmd, opid ctrl.OPID
281
315
return err
282
316
}
283
317
284
- err = r .RunSnapshot (ctx , dump , bcp , nss )
318
+ err = r .RunSnapshot (ctx , dump , bcp , nss , usersAndRolesOpt )
285
319
if err != nil {
286
320
return err
287
321
}
@@ -647,7 +681,13 @@ func (r *Restore) toState(ctx context.Context, status defs.Status, wait *time.Du
647
681
return toState (ctx , r .leadConn , status , r .name , r .nodeInfo , r .reconcileStatus , wait )
648
682
}
649
683
650
- func (r * Restore ) RunSnapshot (ctx context.Context , dump string , bcp * backup.BackupMeta , nss []string ) error {
684
+ func (r * Restore ) RunSnapshot (
685
+ ctx context.Context ,
686
+ dump string ,
687
+ bcp * backup.BackupMeta ,
688
+ nss []string ,
689
+ usersAndRolesOpt restoreUsersAndRolesOption ,
690
+ ) error {
651
691
var rdr io.ReadCloser
652
692
653
693
var err error
@@ -673,7 +713,15 @@ func (r *Restore) RunSnapshot(ctx context.Context, dump string, bcp *backup.Back
673
713
mapRS := util .MakeReverseRSMapFunc (r .rsMap )
674
714
if r .nodeInfo .IsConfigSrv () && util .IsSelective (nss ) {
675
715
// restore cluster specific configs only
676
- return r .configsvrRestore (ctx , bcp , nss , mapRS )
716
+ if err := r .configsvrRestore (ctx , bcp , nss , mapRS ); err != nil {
717
+ return err
718
+ }
719
+ if ! usersAndRolesOpt {
720
+ return nil
721
+ }
722
+
723
+ // selective restore needs to process users and roles from the full backup,
724
+ // so we'll continue with selective restore
677
725
}
678
726
679
727
var cfg * config.Config
@@ -730,17 +778,23 @@ func (r *Restore) RunSnapshot(ctx context.Context, dump string, bcp *backup.Back
730
778
return errors .Wrap (err , "mongorestore" )
731
779
}
732
780
733
- if util .IsSelective (nss ) {
734
- return nil
781
+ if usersAndRolesOpt {
782
+ if err := r .restoreUsersAndRoles (ctx , nss ); err != nil {
783
+ return errors .Wrap (err , "restoring users and roles" )
784
+ }
735
785
}
736
786
787
+ return nil
788
+ }
789
+
790
+ func (r * Restore ) restoreUsersAndRoles (ctx context.Context , nss []string ) error {
737
791
r .log .Info ("restoring users and roles" )
738
792
cusr , err := topo .CurrentUser (ctx , r .nodeConn )
739
793
if err != nil {
740
794
return errors .Wrap (err , "get current user" )
741
795
}
742
796
743
- err = r .swapUsers (ctx , cusr )
797
+ err = r .swapUsers (ctx , cusr , nss )
744
798
if err != nil {
745
799
return errors .Wrap (err , "swap users 'n' roles" )
746
800
}
@@ -1123,22 +1177,39 @@ func (r *Restore) Done(ctx context.Context) error {
1123
1177
return nil
1124
1178
}
1125
1179
1126
- func (r * Restore ) swapUsers (ctx context.Context , exclude * topo.AuthInfo ) error {
1180
+ func (r * Restore ) swapUsers (ctx context.Context , exclude * topo.AuthInfo , nss []string ) error {
1181
+ dbs := []string {}
1182
+ for _ , ns := range nss {
1183
+ // ns can be "*.*" or "admin.pbmRUsers" or "admin.pbmRRoles"
1184
+ db , _ := util .ParseNS (ns )
1185
+ if len (db ) == 0 || strings .HasPrefix (db , defs .DB ) {
1186
+ continue
1187
+ }
1188
+ dbs = append (dbs , db )
1189
+ }
1190
+
1127
1191
rolesC := r .nodeConn .Database ("admin" ).Collection ("system.roles" )
1128
1192
1129
1193
eroles := []string {}
1130
1194
for _ , r := range exclude .UserRoles {
1131
1195
eroles = append (eroles , r .DB + "." + r .Role )
1132
1196
}
1133
1197
1198
+ rolesFilter := bson.M {
1199
+ "_id" : bson.M {"$nin" : eroles },
1200
+ }
1201
+ if len (dbs ) > 0 {
1202
+ rolesFilter ["db" ] = bson.M {"$in" : dbs }
1203
+ }
1204
+
1134
1205
curr , err := r .nodeConn .Database (defs .DB ).Collection (defs .TmpRolesCollection ).
1135
- Find (ctx , bson. M { "_id" : bson. M { "$nin" : eroles }} )
1206
+ Find (ctx , rolesFilter )
1136
1207
if err != nil {
1137
1208
return errors .Wrap (err , "create cursor for tmpRoles" )
1138
1209
}
1139
1210
defer curr .Close (ctx )
1140
1211
1141
- _ , err = rolesC .DeleteMany (ctx , bson. M { "_id" : bson. M { "$nin" : eroles }} )
1212
+ _ , err = rolesC .DeleteMany (ctx , rolesFilter )
1142
1213
if err != nil {
1143
1214
return errors .Wrap (err , "delete current roles" )
1144
1215
}
@@ -1159,15 +1230,21 @@ func (r *Restore) swapUsers(ctx context.Context, exclude *topo.AuthInfo) error {
1159
1230
if len (exclude .Users ) > 0 {
1160
1231
user = exclude .Users [0 ].DB + "." + exclude .Users [0 ].User
1161
1232
}
1233
+ filterUsers := bson.M {
1234
+ "_id" : bson.M {"$ne" : user },
1235
+ }
1236
+ if len (dbs ) > 0 {
1237
+ filterUsers ["db" ] = bson.M {"$in" : dbs }
1238
+ }
1162
1239
cur , err := r .nodeConn .Database (defs .DB ).Collection (defs .TmpUsersCollection ).
1163
- Find (ctx , bson. M { "_id" : bson. M { "$ne" : user }} )
1240
+ Find (ctx , filterUsers )
1164
1241
if err != nil {
1165
1242
return errors .Wrap (err , "create cursor for tmpUsers" )
1166
1243
}
1167
1244
defer cur .Close (ctx )
1168
1245
1169
1246
usersC := r .nodeConn .Database ("admin" ).Collection ("system.users" )
1170
- _ , err = usersC .DeleteMany (ctx , bson. M { "_id" : bson. M { "$ne" : user }} )
1247
+ _ , err = usersC .DeleteMany (ctx , filterUsers )
1171
1248
if err != nil {
1172
1249
return errors .Wrap (err , "delete current users" )
1173
1250
}
0 commit comments