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

Add support for restoring specific snapshot #1927

Merged
merged 3 commits into from
Oct 4, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
28 changes: 22 additions & 6 deletions pkg/restore.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import (
license "go.bytebuilders.dev/license-verifier/kubernetes"
"gomodules.xyz/flags"
"gomodules.xyz/pointer"
go_str "gomodules.xyz/x/strings"
core "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
Expand Down Expand Up @@ -226,14 +227,14 @@ 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

restoreSession, err := opt.stashClient.StashV1beta1().RestoreSessions(opt.namespace).Get(context.TODO(), opt.restoreSessionName, metav1.GetOptions{})
if err != nil {
return nil, err
}
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
}
_, err = stash_cs_util.UpdateRestoreSessionStatus(
context.TODO(),
opt.stashClient.StashV1beta1(),
Expand Down Expand Up @@ -311,9 +312,8 @@ func (opt *mongoOptions) restoreMongoDB(targetRef api_v1beta1.TargetRef) (*resti
Host: hostKey,
SourceHost: hostKey,
FileName: opt.defaultDumpOptions.FileName,
Snapshot: opt.defaultDumpOptions.Snapshot,
Snapshot: opt.getSnapshotForHost(hostKey, restoreSession.Spec.Target.Rules),
hmsayem marked this conversation as resolved.
Show resolved Hide resolved
}

// setup pipe command
restoreCmd := restic.Command{
Name: MongoRestoreCMD,
Expand Down Expand Up @@ -426,3 +426,19 @@ func (opt *mongoOptions) getHostRestoreStats(err error) []api_v1beta1.HostRestor

return restoreStats
}

func (opt *mongoOptions) getSnapshotForHost(hostname string, rules []api_v1beta1.Rule) string {
var hostSnapshot string
for _, rule := range rules {
if len(rule.TargetHosts) == 0 || go_str.Contains(rule.TargetHosts, hostname) {
hostSnapshot = rule.Snapshots[0]
// if rule has empty targetHost then check further rules to see if any other rule with non-empty targetHost matches
if len(rule.TargetHosts) == 0 {
continue
} else {
return hostSnapshot
}
}
}
return hostSnapshot
}
60 changes: 60 additions & 0 deletions vendor/gomodules.xyz/x/strings/fmt.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package strings

import (
"strings"
)

func Fmt(s string) string {
stripper := &Stripe{
Result: "",
}
stripper.Write(s)
return stripper.Result
}

// Striplines wraps an output stream, stripping runs of consecutive empty lines.
// You must call Flush before the output stream will be complete.
// Implements io.WriteCloser, Writer, Closer.
type Stripe struct {
Result string
lastLine []byte
currentLine []byte
}

func (w *Stripe) Write(p string) (int, error) {
totalN := 0
s := string(p)
if !strings.Contains(s, "\n") {
w.currentLine = append(w.currentLine, p...)
return 0, nil
}
cur := string(append(w.currentLine, p...))
lastN := strings.LastIndex(cur, "\n")
s = cur[:lastN]
for _, line := range strings.Split(s, "\n") {
n, err := w.writeLn(line + "\n")
w.lastLine = []byte(line)
if err != nil {
return totalN, err
}
totalN += n
}
rem := cur[(lastN + 1):]
w.currentLine = []byte(rem)
return totalN, nil
}

// Close flushes the last of the output into the underlying writer.
func (w *Stripe) Close() error {
_, err := w.writeLn(string(w.currentLine))
return err
}

func (w *Stripe) writeLn(line string) (n int, err error) {
if strings.TrimSpace(string(w.lastLine)) == "" && strings.TrimSpace(line) == "" {
return 0, nil
} else {
w.Result = w.Result + line
return len(line), nil
}
}
14 changes: 14 additions & 0 deletions vendor/gomodules.xyz/x/strings/optionals.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package strings

import "log"

func VString(def string, args ...string) string {
v := def
if len(args) == 1 {
v = args[0]
} else if len(args) > 1 {
v = args[0]
log.Printf("Found more than 1 argument when expected 1 %v", args)
}
return v
}
11 changes: 11 additions & 0 deletions vendor/gomodules.xyz/x/strings/preconditions.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package strings

import "strings"

func Val(v string, def string) string {
trimmed := strings.TrimSpace(v)
if trimmed == "" {
return def
}
return trimmed
}
112 changes: 112 additions & 0 deletions vendor/gomodules.xyz/x/strings/strings.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package strings

import (
"sort"
"strings"
"unicode/utf8"
)

// Benchmark 19246 ns/op.
func Reverse(s string) string {
size := len(s)
buf := make([]byte, size)
for start := 0; start < size; {
r, n := utf8.DecodeRuneInString(s[start:])
start += n
utf8.EncodeRune(buf[size-start:], r)
}
return string(buf)
}

func PrefixFold(s, prefix string) bool {
return len(s) >= len(prefix) && strings.EqualFold(prefix, s[:len(prefix)])
}

func IsEmpty(s *string) bool {
return s == nil || *s == ""
}

func IsBothAlphaNum(a string) bool {
alpha := false
num := false
for _, c := range a {
if (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') {
alpha = true
} else if c >= '0' && c <= '9' {
num = true
}
if alpha && num {
return true
}
}
return false
}

func Contains(a []string, e string) bool {
for _, s := range a {
if s == e {
return true
}
}
return false
}

// Allowed char: [a-z0-9]([a-z0-9-]*[a-z0-9])?
// Makes it safe as a subdomain
func DomainForm(s string) string {
runes := make([]rune, len(s))
for i, r := range strings.ToLower(s) {
if (r >= '0' && r <= '9') || (r >= 'a' && r <= 'z') || (r == '-') || (r == '.') {
runes[i] = r
} else if r == '_' {
runes[i] = '-' // _ --> -
}
}
return strings.Trim(string(runes), "-")
}

func Filter(s []string, f func(string) bool) []string {
ret := make([]string, 0)
for _, elm := range s {
if !f(elm) {
ret = append(ret, elm)
}
}
return ret
}

func Join(a []*string, sep string) string {
b := make([]string, len(a))
for i, s := range a {
b[i] = *s
}
return strings.Join(b, sep)
}

func EqualSlice(a, b []string) bool {
if a == nil && b == nil {
return true
}

if a == nil || b == nil {
return false
}

if len(a) != len(b) {
return false
}

// Copy slices
aCopy := append([]string(nil), a...)
bCopy := append([]string(nil), b...)

sort.Strings(aCopy)
sort.Strings(bCopy)

for i := range aCopy {
if aCopy[i] != bCopy[i] {
return false
}
}
return true
}
1 change: 1 addition & 0 deletions vendor/modules.txt
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ gomodules.xyz/wait
# gomodules.xyz/x v0.0.15
## explicit; go 1.18
gomodules.xyz/x/arrays
gomodules.xyz/x/strings
gomodules.xyz/x/version
# google.golang.org/appengine v1.6.7
## explicit; go 1.11
Expand Down
Loading