/
config.go
210 lines (179 loc) · 4.69 KB
/
config.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
/*
Copyright AppsCode Inc. and Contributors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package restic
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"sort"
"stash.appscode.dev/apimachinery/apis/stash/v1alpha1"
shell "gomodules.xyz/go-sh"
core "k8s.io/api/core/v1"
ofst "kmodules.xyz/offshoot-api/api/v1"
)
const (
DefaultOutputFileName = "output.json"
DefaultScratchDir = "/tmp"
DefaultHost = "host-0"
)
type ResticWrapper struct {
sh *shell.Session
config SetupOptions
}
type Command struct {
Name string
Args []interface{}
}
// BackupOptions specifies backup information
// if StdinPipeCommands is specified, BackupPaths will not be used
type BackupOptions struct {
Host string
BackupPaths []string
StdinPipeCommands []Command
StdinFileName string // default "stdin"
RetentionPolicy v1alpha1.RetentionPolicy
Exclude []string
Args []string
}
// RestoreOptions specifies restore information
type RestoreOptions struct {
Host string
SourceHost string
RestorePaths []string
Snapshots []string // when Snapshots are specified SourceHost and RestorePaths will not be used
Destination string // destination path where snapshot will be restored, used in cli
Exclude []string
Include []string
Args []string
}
type DumpOptions struct {
Host string
SourceHost string
Snapshot string // default "latest"
Path string
FileName string // default "stdin"
StdoutPipeCommands []Command
}
type SetupOptions struct {
Provider string
Bucket string
Endpoint string
Region string
Path string
CacertFile string
ScratchDir string
EnableCache bool
MaxConnections int64
StorageSecret *core.Secret
Nice *ofst.NiceSettings
IONice *ofst.IONiceSettings
}
func NewResticWrapper(options SetupOptions) (*ResticWrapper, error) {
wrapper := &ResticWrapper{
sh: shell.NewSession(),
config: options,
}
err := wrapper.configure()
if err != nil {
return nil, err
}
return wrapper, nil
}
func NewResticWrapperFromShell(options SetupOptions, sh *shell.Session) (*ResticWrapper, error) {
wrapper := &ResticWrapper{
sh: sh,
config: options,
}
err := wrapper.configure()
if err != nil {
return nil, err
}
return wrapper, nil
}
func (w *ResticWrapper) configure() error {
w.sh.SetDir(w.config.ScratchDir)
w.sh.ShowCMD = true
w.sh.PipeFail = true
w.sh.PipeStdErrors = true
// Setup restic environments
return w.setupEnv()
}
func (w *ResticWrapper) SetEnv(key, value string) {
if w.sh != nil {
w.sh.SetEnv(key, value)
}
}
func (w *ResticWrapper) GetEnv(key string) string {
if w.sh != nil {
return w.sh.Env[key]
}
return ""
}
func (w *ResticWrapper) GetCaPath() string {
return w.config.CacertFile
}
func (w *ResticWrapper) DumpEnv(path string, dumpedFile string) error {
if err := os.MkdirAll(path, 0o755); err != nil {
return err
}
var envs string
if w.sh != nil {
sortedKeys := make([]string, 0, len(w.sh.Env))
for k := range w.sh.Env {
sortedKeys = append(sortedKeys, k)
}
sort.Strings(sortedKeys) // sort by key
for _, v := range sortedKeys {
envs = envs + fmt.Sprintln(v+"="+w.sh.Env[v])
}
}
if err := ioutil.WriteFile(filepath.Join(path, dumpedFile), []byte(envs), 0o600); err != nil {
return err
}
return nil
}
func (w *ResticWrapper) HideCMD() {
if w.sh != nil {
w.sh.ShowCMD = false
}
}
func (w *ResticWrapper) GetRepo() string {
if w.sh != nil {
return w.sh.Env[RESTIC_REPOSITORY]
}
return ""
}
// Copy function copy input ResticWrapper and returns a new wrapper with copy of its content.
func (w *ResticWrapper) Copy() *ResticWrapper {
if w == nil {
return nil
}
out := new(ResticWrapper)
if w.sh != nil {
out.sh = shell.NewSession()
// set values in.sh to out.sh
for k, v := range w.sh.Env {
out.sh.Env[k] = v
}
// don't use same stdin, stdout, stderr for each instant to avoid data race.
// out.sh.Stdin = in.sh.Stdin
// out.sh.Stdout = in.sh.Stdout
// out.sh.Stderr = in.sh.Stderr
out.sh.ShowCMD = w.sh.ShowCMD
out.sh.PipeFail = w.sh.PipeFail
out.sh.PipeStdErrors = w.sh.PipeStdErrors
}
out.config = w.config
return out
}