Skip to content

Commit d54d6af

Browse files
Fix mg 6.0.5 backup-restore (#1908)
Signed-off-by: Arnob Kumar Saha <arnob@appscode.com>
1 parent 2687ede commit d54d6af

File tree

4 files changed

+63
-76
lines changed

4 files changed

+63
-76
lines changed

Dockerfile.in

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ LABEL org.opencontainers.image.source https://github.com/stashed/mongodb
3535
COPY --from=0 /restic /bin/restic
3636
COPY bin/{ARG_OS}_{ARG_ARCH}/{ARG_BIN} /{ARG_BIN}
3737

38-
USER 65534
38+
# https://github.com/docker-library/mongo/blob/master/6.0/Dockerfile#L12
39+
USER 999
3940

4041
ENTRYPOINT ["/{ARG_BIN}"]

pkg/backup.go

Lines changed: 32 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@ func NewCmdBackup() *cobra.Command {
8484
masterURL string
8585
kubeconfigPath string
8686
opt = mongoOptions{
87-
totalHosts: 1,
8887
waitTimeout: 300,
8988
setupOptions: restic.SetupOptions{
9089
ScratchDir: restic.DefaultScratchDir,
@@ -150,8 +149,14 @@ func NewCmdBackup() *cobra.Command {
150149
if err != nil {
151150
backupOutput = &restic.BackupOutput{
152151
BackupTargetStatus: api_v1beta1.BackupTargetStatus{
153-
Ref: targetRef,
154-
Stats: opt.getHostBackupStats(err),
152+
Ref: targetRef,
153+
Stats: []api_v1beta1.HostBackupStats{
154+
{
155+
Hostname: opt.defaultBackupOptions.Host,
156+
Phase: api_v1beta1.HostBackupFailed,
157+
Error: err.Error(),
158+
},
159+
},
155160
},
156161
}
157162
}
@@ -295,9 +300,9 @@ func (opt *mongoOptions) backupMongoDB(targetRef api_v1beta1.TargetRef) (*restic
295300
// 3. For sharded MongoDB, totalHosts=(number of shard + 1) // extra 1 for config server
296301
// So, for stand-alone MongoDB and MongoDB ReplicaSet, we don't have to do anything.
297302
// We only need to update totalHosts field for sharded MongoDB
303+
298304
// For sharded MongoDB, parameter.ConfigServer will not be empty
299305
if parameters.ConfigServer != "" {
300-
opt.totalHosts = len(parameters.ReplicaSets) + 1 // for each shard there will be one key in parameters.ReplicaSet
301306
backupSession, err := opt.stashClient.StashV1beta1().BackupSessions(opt.namespace).Get(context.TODO(), opt.backupSessionName, metav1.GetOptions{})
302307
if err != nil {
303308
return nil, err
@@ -309,7 +314,7 @@ func (opt *mongoOptions) backupMongoDB(targetRef api_v1beta1.TargetRef) (*restic
309314
opt.stashClient.StashV1beta1(),
310315
backupSession.ObjectMeta,
311316
func(status *api_v1beta1.BackupSessionStatus) (types.UID, *api_v1beta1.BackupSessionStatus) {
312-
status.Targets[i].TotalHosts = pointer.Int32P(int32(opt.totalHosts))
317+
status.Targets[i].TotalHosts = pointer.Int32P(int32(len(parameters.ReplicaSets) + 1)) // for each shard there will be one key in parameters.ReplicaSet
313318
return backupSession.UID, status
314319
},
315320
metav1.UpdateOptions{},
@@ -371,7 +376,15 @@ func (opt *mongoOptions) backupMongoDB(targetRef api_v1beta1.TargetRef) (*restic
371376
"--authenticationDatabase", "$external",
372377
}
373378
mongoCreds = append(mongoCreds, userAuth...)
374-
dumpCreds = append(dumpCreds, userAuth...)
379+
username := StashUserName
380+
if parameters.ConfigServer == "" {
381+
username = string(authSecret.Data[MongoUserKey])
382+
}
383+
dumpCreds = append(dumpCreds, []interface{}{
384+
fmt.Sprintf("--username=%s", username),
385+
fmt.Sprintf("--password=%s", authSecret.Data[MongoPasswordKey]),
386+
"--authenticationDatabase", opt.authenticationDatabase,
387+
}...)
375388

376389
} else {
377390
userAuth := []interface{}{
@@ -380,7 +393,15 @@ func (opt *mongoOptions) backupMongoDB(targetRef api_v1beta1.TargetRef) (*restic
380393
"--authenticationDatabase", opt.authenticationDatabase,
381394
}
382395
mongoCreds = append(mongoCreds, userAuth...)
383-
dumpCreds = append(dumpCreds, userAuth...)
396+
username := StashUserName
397+
if parameters.ConfigServer == "" {
398+
username = string(authSecret.Data[MongoUserKey])
399+
}
400+
dumpCreds = append(dumpCreds, []interface{}{
401+
fmt.Sprintf("--username=%s", username),
402+
fmt.Sprintf("--password=%s", authSecret.Data[MongoPasswordKey]),
403+
"--authenticationDatabase", opt.authenticationDatabase,
404+
}...)
384405
}
385406

386407
getBackupOpt := func(mongoDSN, hostKey string, isStandalone bool) restic.BackupOptions {
@@ -568,12 +589,7 @@ func (opt *mongoOptions) backupMongoDB(targetRef api_v1beta1.TargetRef) (*restic
568589
// hide password, don't print cmd
569590
resticWrapper.HideCMD()
570591

571-
out, err := resticWrapper.RunParallelBackup(opt.backupOptions, targetRef, opt.maxConcurrency)
572-
if err != nil {
573-
klog.Warningln("backup failed!", err.Error())
574-
}
575-
// error not returned, error is encoded into output
576-
return out, nil
592+
return resticWrapper.RunParallelBackup(opt.backupOptions, targetRef, opt.maxConcurrency)
577593
}
578594

579595
// cleanup usually unlocks the locked servers
@@ -585,32 +601,6 @@ func cleanup() {
585601
}
586602
}
587603

588-
func (opt *mongoOptions) getHostBackupStats(err error) []api_v1beta1.HostBackupStats {
589-
var backupStats []api_v1beta1.HostBackupStats
590-
591-
errMsg := fmt.Sprintf("failed to start backup: %s", err.Error())
592-
for _, backupOpt := range opt.backupOptions {
593-
backupStats = append(backupStats, api_v1beta1.HostBackupStats{
594-
Hostname: backupOpt.Host,
595-
Phase: api_v1beta1.HostBackupFailed,
596-
Error: errMsg,
597-
})
598-
}
599-
600-
if opt.totalHosts > len(backupStats) {
601-
rem := opt.totalHosts - len(backupStats)
602-
for i := 0; i < rem; i++ {
603-
backupStats = append(backupStats, api_v1beta1.HostBackupStats{
604-
Hostname: fmt.Sprintf("unknown-%s", strconv.Itoa(i)),
605-
Phase: api_v1beta1.HostBackupFailed,
606-
Error: errMsg,
607-
})
608-
}
609-
}
610-
611-
return backupStats
612-
}
613-
614604
func getSSLUser(path string) (string, error) {
615605
data, err := sh.Command(OpenSSLCMD, "x509", "-in", path, "-inform", "PEM", "-subject", "-nameopt", "RFC2253", "-noout").Output()
616606
if err != nil {
@@ -687,7 +677,7 @@ func disabelBalancer(mongosHost string) error {
687677
"config",
688678
"--host", mongosHost,
689679
"--quiet",
690-
"--eval", "while(sh.isBalancerRunning()){ print('waiting for balancer to stop...'); sleep(1000);}",
680+
"--eval", "while(sh.isBalancerRunning().mode != 'off'){ print('waiting for balancer to stop...'); sleep(1000);}",
691681
}, mongoCreds...)
692682
if err := sh.Command(MongoCMD, args...).Command("/usr/bin/tail", "-1").Run(); err != nil {
693683
return err
@@ -731,7 +721,7 @@ func lockConfigServer(configSVRDSN, secondaryHost string) error {
731721
"config",
732722
"--host", configSVRDSN,
733723
"--quiet",
734-
"--eval", "db.BackupControl.findAndModify({query: { _id: 'BackupControlDocument' }, update: { $inc: { counter : 1 } }, new: true, upsert: true, writeConcern: { w: 'majority', wtimeout: 15000 }});",
724+
"--eval", "JSON.stringify(db.BackupControl.findAndModify({query: { _id: 'BackupControlDocument' }, update: { $inc: { counter : 1 } }, new: true, upsert: true, writeConcern: { w: 'majority', wtimeout: 15000 }}));",
735725
}, mongoCreds...)
736726
if err := sh.Command(MongoCMD, args...).Command("/usr/bin/tail", "-1").UnmarshalJSON(&v); err != nil {
737727
return err
@@ -750,7 +740,7 @@ func lockConfigServer(configSVRDSN, secondaryHost string) error {
750740
"config",
751741
"--host", secondaryHost,
752742
"--quiet",
753-
"--eval", "rs.secondaryOk(); db.BackupControl.find({ '_id' : 'BackupControlDocument' }).readConcern('majority');",
743+
"--eval", "rs.secondaryOk(); JSON.stringify(db.BackupControl.find({ '_id' : 'BackupControlDocument' }).readConcern('majority').toArray());",
754744
}, mongoCreds...)
755745

756746
if err := sh.Command(MongoCMD, args...).Command("/usr/bin/tail", "-1").UnmarshalJSON(&v2); err != nil {

pkg/restore.go

Lines changed: 29 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import (
2222
"fmt"
2323
"os"
2424
"path/filepath"
25-
"strconv"
2625
"strings"
2726

2827
api_v1beta1 "stash.appscode.dev/apimachinery/apis/stash/v1beta1"
@@ -34,6 +33,7 @@ import (
3433
"github.com/spf13/cobra"
3534
license "go.bytebuilders.dev/license-verifier/kubernetes"
3635
"gomodules.xyz/flags"
36+
"gomodules.xyz/go-sh"
3737
"gomodules.xyz/pointer"
3838
core "k8s.io/api/core/v1"
3939
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -106,8 +106,14 @@ func NewCmdRestore() *cobra.Command {
106106
if err != nil {
107107
restoreOutput = &restic.RestoreOutput{
108108
RestoreTargetStatus: api_v1beta1.RestoreMemberStatus{
109-
Ref: targetRef,
110-
Stats: opt.getHostRestoreStats(err),
109+
Ref: targetRef,
110+
Stats: []api_v1beta1.HostRestoreStats{
111+
{
112+
Hostname: opt.defaultDumpOptions.Host,
113+
Phase: api_v1beta1.HostRestoreFailed,
114+
Error: err.Error(),
115+
},
116+
},
111117
},
112118
}
113119
}
@@ -226,10 +232,8 @@ func (opt *mongoOptions) restoreMongoDB(targetRef api_v1beta1.TargetRef) (*resti
226232
// So, for stand-alone MongoDB and MongoDB ReplicaSet, we don't have to do anything.
227233
// We only need to update totalHosts field for sharded MongoDB
228234

229-
opt.totalHosts = 1
230235
// For sharded MongoDB, parameter.ConfigServer will not be empty
231236
if parameters.ConfigServer != "" {
232-
opt.totalHosts = len(parameters.ReplicaSets) + 1 // for each shard there will be one key in parameters.ReplicaSet
233237
restoreSession, err := opt.stashClient.StashV1beta1().RestoreSessions(opt.namespace).Get(context.TODO(), opt.restoreSessionName, metav1.GetOptions{})
234238
if err != nil {
235239
return nil, err
@@ -239,7 +243,7 @@ func (opt *mongoOptions) restoreMongoDB(targetRef api_v1beta1.TargetRef) (*resti
239243
opt.stashClient.StashV1beta1(),
240244
restoreSession.ObjectMeta,
241245
func(status *api_v1beta1.RestoreSessionStatus) (types.UID, *api_v1beta1.RestoreSessionStatus) {
242-
status.TotalHosts = pointer.Int32P(int32(opt.totalHosts))
246+
status.TotalHosts = pointer.Int32P(int32(len(parameters.ReplicaSets) + 1)) // for each shard there will be one key in parameters.ReplicaSet
243247
return restoreSession.UID, status
244248
},
245249
metav1.UpdateOptions{},
@@ -393,36 +397,29 @@ func (opt *mongoOptions) restoreMongoDB(targetRef api_v1beta1.TargetRef) (*resti
393397
resticWrapper.HideCMD()
394398

395399
// Run dump
396-
out, err := resticWrapper.ParallelDump(opt.dumpOptions, targetRef, opt.maxConcurrency)
400+
restoreOutput, err := resticWrapper.ParallelDump(opt.dumpOptions, targetRef, opt.maxConcurrency)
397401
if err != nil {
398-
klog.Warningln("restore failed!", err.Error())
399-
}
400-
// error not returned, error is encoded into output
401-
return out, nil
402-
}
403-
404-
func (opt *mongoOptions) getHostRestoreStats(err error) []api_v1beta1.HostRestoreStats {
405-
var restoreStats []api_v1beta1.HostRestoreStats
406-
407-
errMsg := fmt.Sprintf("failed to start data restoration: %s", err.Error())
408-
for _, dumpOpt := range opt.dumpOptions {
409-
restoreStats = append(restoreStats, api_v1beta1.HostRestoreStats{
410-
Hostname: dumpOpt.Host,
411-
Phase: api_v1beta1.HostRestoreFailed,
412-
Error: errMsg,
413-
})
402+
return nil, err
414403
}
415404

416-
if opt.totalHosts > len(restoreStats) {
417-
rem := opt.totalHosts - len(restoreStats)
418-
for i := 0; i < rem; i++ {
419-
restoreStats = append(restoreStats, api_v1beta1.HostRestoreStats{
420-
Hostname: fmt.Sprintf("unknown-%s", strconv.Itoa(i)),
421-
Phase: api_v1beta1.HostRestoreFailed,
422-
Error: errMsg,
423-
})
405+
if parameters.ConfigServer != "" {
406+
err = dropTempReshardCollection(parameters.ConfigServer)
407+
if err != nil {
408+
klog.Errorf("error while deleting temporary reshard collection for %v. error: %v", parameters.ConfigServer, err)
409+
return nil, err
424410
}
425411
}
426412

427-
return restoreStats
413+
return restoreOutput, nil
414+
}
415+
416+
func dropTempReshardCollection(configsvrDSN string) error {
417+
args := append([]interface{}{
418+
"config",
419+
"--host", configsvrDSN,
420+
"--quiet",
421+
"--eval", `db.reshardingOperations_temp.drop()`,
422+
}, mongoCreds...)
423+
424+
return sh.Command(MongoCMD, args...).Command("/usr/bin/tail", "-1").Run()
428425
}

pkg/utils.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ type mongoOptions struct {
6868
dumpOptions []restic.DumpOptions
6969
defaultDumpOptions restic.DumpOptions
7070
config *restclient.Config
71-
totalHosts int
7271
}
7372

7473
func waitForDBReady(host string, port, waitTimeout int32) {

0 commit comments

Comments
 (0)