Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[cherry-pick] Fix component status updating for shard backup and restore (#1806) #1824

Merged
merged 1 commit into from
May 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 25 additions & 25 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,33 @@ go 1.18

require (
github.com/pkg/errors v0.9.1
github.com/spf13/cobra v1.6.0
github.com/spf13/cobra v1.7.0
go.bytebuilders.dev/license-verifier/kubernetes v0.12.0
gomodules.xyz/flags v0.1.3
gomodules.xyz/go-sh v0.1.0
gomodules.xyz/logs v0.0.6
gomodules.xyz/pointer v0.1.0
gomodules.xyz/x v0.0.14
k8s.io/api v0.25.1
gomodules.xyz/x v0.0.15
k8s.io/api v0.25.3
k8s.io/apimachinery v0.25.3
k8s.io/client-go v0.25.1
k8s.io/client-go v0.25.3
k8s.io/klog/v2 v2.80.1
kmodules.xyz/client-go v0.25.19
kmodules.xyz/custom-resources v0.25.0
kmodules.xyz/offshoot-api v0.25.0
kubedb.dev/apimachinery v0.28.4-0.20220918021210-a0b96812228b
stash.appscode.dev/apimachinery v0.29.0
kmodules.xyz/client-go v0.25.23
kmodules.xyz/custom-resources v0.25.1
kmodules.xyz/offshoot-api v0.25.3
kubedb.dev/apimachinery v0.33.1
stash.appscode.dev/apimachinery v0.29.1-0.20230529131221-1e979c48da10
)

require (
cloud.google.com/go v0.99.0 // indirect
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
github.com/Azure/go-autorest/autorest v0.11.27 // indirect
github.com/Azure/go-autorest/autorest/adal v0.9.20 // indirect
github.com/Azure/go-autorest/autorest v0.11.28 // indirect
github.com/Azure/go-autorest/autorest/adal v0.9.21 // indirect
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
github.com/Azure/go-autorest/logger v0.2.1 // indirect
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
github.com/Masterminds/semver/v3 v3.1.1 // indirect
github.com/Masterminds/semver/v3 v3.2.1 // indirect
github.com/armon/circbuf v0.0.0-20190214190532-5111143e8da2 // indirect
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
Expand All @@ -49,7 +49,7 @@ require (
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/imdario/mergo v0.3.13 // indirect
github.com/inconshreveable/mousetrap v1.0.1 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
Expand All @@ -62,16 +62,16 @@ require (
github.com/yudai/gojsondiff v1.0.0 // indirect
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect
go.bytebuilders.dev/license-proxyserver v0.0.3 // indirect
go.bytebuilders.dev/license-verifier v0.12.1-0.20221113063237-6eb88040dd50 // indirect
golang.org/x/crypto v0.6.0 // indirect
golang.org/x/net v0.7.0 // indirect
go.bytebuilders.dev/license-verifier v0.12.1 // indirect
golang.org/x/crypto v0.9.0 // indirect
golang.org/x/net v0.10.0 // indirect
golang.org/x/oauth2 v0.5.0 // indirect
golang.org/x/sys v0.5.0 // indirect
golang.org/x/term v0.5.0 // indirect
golang.org/x/text v0.7.0 // indirect
golang.org/x/time v0.1.0 // indirect
golang.org/x/sys v0.8.0 // indirect
golang.org/x/term v0.8.0 // indirect
golang.org/x/text v0.9.0 // indirect
golang.org/x/time v0.3.0 // indirect
gomodules.xyz/clock v0.0.0-20200817085942-06523dba733f // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.3.0 // indirect
gomodules.xyz/mergo v0.3.13 // indirect
gomodules.xyz/sets v0.2.1 // indirect
gomodules.xyz/wait v0.2.0 // indirect
Expand All @@ -80,11 +80,11 @@ require (
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/apiextensions-apiserver v0.25.1 // indirect
k8s.io/apiserver v0.25.1 // indirect
k8s.io/apiextensions-apiserver v0.25.3 // indirect
k8s.io/apiserver v0.25.3 // indirect
k8s.io/kube-aggregator v0.25.1 // indirect
k8s.io/kube-openapi v0.0.0-20220803164354-a70c9af30aea // indirect
k8s.io/utils v0.0.0-20220823124924-e9cbc92d1a73 // indirect
k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect
k8s.io/utils v0.0.0-20221012122500-cfd413dd9e85 // indirect
kmodules.xyz/apiversion v0.2.0 // indirect
kmodules.xyz/objectstore-api v0.25.1-0.20221104003322-f0289b5b6ca2 // indirect
kmodules.xyz/prober v0.25.0 // indirect
Expand Down
112 changes: 54 additions & 58 deletions go.sum

Large diffs are not rendered by default.

48 changes: 38 additions & 10 deletions pkg/backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"os/exec"
"os/signal"
"path/filepath"
"strconv"
"strings"
"syscall"
"time"
Expand Down Expand Up @@ -143,14 +144,8 @@ func NewCmdBackup() *cobra.Command {
if err != nil {
backupOutput = &restic.BackupOutput{
BackupTargetStatus: api_v1beta1.BackupTargetStatus{
Ref: targetRef,
Stats: []api_v1beta1.HostBackupStats{
{
Hostname: opt.defaultBackupOptions.Host,
Phase: api_v1beta1.HostBackupFailed,
Error: err.Error(),
},
},
Ref: targetRef,
Stats: opt.getHostBackupStats(err),
},
}
}
Expand Down Expand Up @@ -295,8 +290,10 @@ func (opt *mongoOptions) backupMongoDB(targetRef api_v1beta1.TargetRef) (*restic
// So, for stand-alone MongoDB and MongoDB ReplicaSet, we don't have to do anything.
// We only need to update totalHosts field for sharded MongoDB

opt.totalHosts = 1
// For sharded MongoDB, parameter.ConfigServer will not be empty
if parameters.ConfigServer != "" {
opt.totalHosts = len(parameters.ReplicaSets) + 1 // for each shard there will be one key in parameters.ReplicaSet
backupSession, err := opt.stashClient.StashV1beta1().BackupSessions(opt.namespace).Get(context.TODO(), opt.backupSessionName, metav1.GetOptions{})
if err != nil {
return nil, err
Expand All @@ -308,7 +305,7 @@ func (opt *mongoOptions) backupMongoDB(targetRef api_v1beta1.TargetRef) (*restic
opt.stashClient.StashV1beta1(),
backupSession.ObjectMeta,
func(status *api_v1beta1.BackupSessionStatus) (types.UID, *api_v1beta1.BackupSessionStatus) {
status.Targets[i].TotalHosts = pointer.Int32P(int32(len(parameters.ReplicaSets) + 1)) // for each shard there will be one key in parameters.ReplicaSet
status.Targets[i].TotalHosts = pointer.Int32P(int32(opt.totalHosts))
return backupSession.UID, status
},
metav1.UpdateOptions{},
Expand Down Expand Up @@ -524,7 +521,12 @@ func (opt *mongoOptions) backupMongoDB(targetRef api_v1beta1.TargetRef) (*restic
// hide password, don't print cmd
resticWrapper.HideCMD()

return resticWrapper.RunParallelBackup(opt.backupOptions, targetRef, opt.maxConcurrency)
out, err := resticWrapper.RunParallelBackup(opt.backupOptions, targetRef, opt.maxConcurrency)
if err != nil {
klog.Warningln("backup failed!", err.Error())
}
// error not returned, error is encoded into output
return out, nil
}

// cleanup usually unlocks the locked servers
Expand All @@ -536,6 +538,32 @@ func cleanup() {
}
}

func (opt *mongoOptions) getHostBackupStats(err error) []api_v1beta1.HostBackupStats {
var backupStats []api_v1beta1.HostBackupStats

errMsg := fmt.Sprintf("failed to start backup: %s", err.Error())
for _, backupOpt := range opt.backupOptions {
backupStats = append(backupStats, api_v1beta1.HostBackupStats{
Hostname: backupOpt.Host,
Phase: api_v1beta1.HostBackupFailed,
Error: errMsg,
})
}

if opt.totalHosts > len(backupStats) {
rem := opt.totalHosts - len(backupStats)
for i := 0; i < rem; i++ {
backupStats = append(backupStats, api_v1beta1.HostBackupStats{
Hostname: fmt.Sprintf("unknown-%s", strconv.Itoa(i)),
Phase: api_v1beta1.HostBackupFailed,
Error: errMsg,
})
}
}

return backupStats
}

func getSSLUser(path string) (string, error) {
data, err := sh.Command(OpenSSLCMD, "x509", "-in", path, "-inform", "PEM", "-subject", "-nameopt", "RFC2253", "-noout").Output()
if err != nil {
Expand Down
48 changes: 38 additions & 10 deletions pkg/restore.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"fmt"
"os"
"path/filepath"
"strconv"
"strings"

api_v1beta1 "stash.appscode.dev/apimachinery/apis/stash/v1beta1"
Expand Down Expand Up @@ -105,14 +106,8 @@ func NewCmdRestore() *cobra.Command {
if err != nil {
restoreOutput = &restic.RestoreOutput{
RestoreTargetStatus: api_v1beta1.RestoreMemberStatus{
Ref: targetRef,
Stats: []api_v1beta1.HostRestoreStats{
{
Hostname: opt.defaultDumpOptions.Host,
Phase: api_v1beta1.HostRestoreFailed,
Error: err.Error(),
},
},
Ref: targetRef,
Stats: opt.getHostRestoreStats(err),
},
}
}
Expand Down Expand Up @@ -231,8 +226,10 @@ func (opt *mongoOptions) restoreMongoDB(targetRef api_v1beta1.TargetRef) (*resti
// So, for stand-alone MongoDB and MongoDB ReplicaSet, we don't have to do anything.
// We only need to update totalHosts field for sharded MongoDB

opt.totalHosts = 1
// For sharded MongoDB, parameter.ConfigServer will not be empty
if parameters.ConfigServer != "" {
opt.totalHosts = len(parameters.ReplicaSets) + 1 // for each shard there will be one key in parameters.ReplicaSet
restoreSession, err := opt.stashClient.StashV1beta1().RestoreSessions(opt.namespace).Get(context.TODO(), opt.restoreSessionName, metav1.GetOptions{})
if err != nil {
return nil, err
Expand All @@ -242,7 +239,7 @@ func (opt *mongoOptions) restoreMongoDB(targetRef api_v1beta1.TargetRef) (*resti
opt.stashClient.StashV1beta1(),
restoreSession.ObjectMeta,
func(status *api_v1beta1.RestoreSessionStatus) (types.UID, *api_v1beta1.RestoreSessionStatus) {
status.TotalHosts = pointer.Int32P(int32(len(parameters.ReplicaSets) + 1)) // for each shard there will be one key in parameters.ReplicaSet
status.TotalHosts = pointer.Int32P(int32(opt.totalHosts))
return restoreSession.UID, status
},
metav1.UpdateOptions{},
Expand Down Expand Up @@ -396,5 +393,36 @@ func (opt *mongoOptions) restoreMongoDB(targetRef api_v1beta1.TargetRef) (*resti
resticWrapper.HideCMD()

// Run dump
return resticWrapper.ParallelDump(opt.dumpOptions, targetRef, opt.maxConcurrency)
out, err := resticWrapper.ParallelDump(opt.dumpOptions, targetRef, opt.maxConcurrency)
if err != nil {
klog.Warningln("restore failed!", err.Error())
}
// error not returned, error is encoded into output
return out, nil
}

func (opt *mongoOptions) getHostRestoreStats(err error) []api_v1beta1.HostRestoreStats {
var restoreStats []api_v1beta1.HostRestoreStats

errMsg := fmt.Sprintf("failed to start data restoration: %s", err.Error())
for _, dumpOpt := range opt.dumpOptions {
restoreStats = append(restoreStats, api_v1beta1.HostRestoreStats{
Hostname: dumpOpt.Host,
Phase: api_v1beta1.HostRestoreFailed,
Error: errMsg,
})
}

if opt.totalHosts > len(restoreStats) {
rem := opt.totalHosts - len(restoreStats)
for i := 0; i < rem; i++ {
restoreStats = append(restoreStats, api_v1beta1.HostRestoreStats{
Hostname: fmt.Sprintf("unknown-%s", strconv.Itoa(i)),
Phase: api_v1beta1.HostRestoreFailed,
Error: errMsg,
})
}
}

return restoreStats
}
1 change: 1 addition & 0 deletions pkg/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ type mongoOptions struct {
dumpOptions []restic.DumpOptions
defaultDumpOptions restic.DumpOptions
config *restclient.Config
totalHosts int
}

func waitForDBReady(host string, port, waitTimeout int32) {
Expand Down
23 changes: 12 additions & 11 deletions vendor/github.com/Masterminds/semver/v3/.golangci.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions vendor/github.com/Masterminds/semver/v3/CHANGELOG.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 5 additions & 12 deletions vendor/github.com/Masterminds/semver/v3/Makefile

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading