@@ -4,23 +4,29 @@ import (
4
4
"fmt"
5
5
"io/ioutil"
6
6
"os"
7
+ "os/exec"
8
+ "os/user"
7
9
"path/filepath"
8
10
9
11
"github.com/appscode/go/flags"
10
12
"github.com/appscode/go/log"
13
+ "github.com/appscode/stash/pkg/cmds/docker"
11
14
"github.com/appscode/stash/pkg/restic"
12
15
"github.com/appscode/stash/pkg/util"
13
16
"github.com/spf13/cobra"
17
+ core "k8s.io/api/core/v1"
14
18
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
15
19
)
16
20
17
21
func NewDownloadCmd () * cobra.Command {
18
22
var (
19
- kubeConfig string
20
- repositoryName string
21
- namespace string
22
- restoreOpt = restic.RestoreOptions {
23
- SourceHost : restic .DefaultHost ,
23
+ kubeConfig string
24
+ repositoryName string
25
+ namespace string
26
+ localDestination string
27
+ restoreOpt = restic.RestoreOptions {
28
+ SourceHost : restic .DefaultHost ,
29
+ Destination : docker .DestinationDir ,
24
30
}
25
31
)
26
32
@@ -42,55 +48,37 @@ func NewDownloadCmd() *cobra.Command {
42
48
if err != nil {
43
49
return err
44
50
}
45
-
46
51
// unlock local backend
47
52
if repository .Spec .Backend .Local != nil {
48
53
return fmt .Errorf ("can't restore from repository with local backend" )
49
54
}
50
-
51
- // get source repository secret
55
+ // get repository secret
52
56
secret , err := c .kubeClient .CoreV1 ().Secrets (namespace ).Get (repository .Spec .Backend .StorageSecretName , metav1.GetOptions {})
53
57
if err != nil {
54
58
return err
55
59
}
56
60
57
- // cleanup whole scratch/secret dir at the end
58
- defer os .RemoveAll (cliScratchDir )
59
- defer os .RemoveAll (cliSecretDir )
60
-
61
- // write repository secrets in a temp dir
62
- if err := os .MkdirAll (cliSecretDir , 0755 ); err != nil {
63
- return err
64
- }
65
- for key , value := range secret .Data {
66
- if err := ioutil .WriteFile (filepath .Join (cliSecretDir , key ), value , 0755 ); err != nil {
67
- return err
68
- }
69
- }
70
-
71
61
// configure restic wrapper
72
62
extraOpt := util.ExtraOptions {
73
- SecretDir : cliSecretDir ,
63
+ SecretDir : docker . SecretDir ,
74
64
EnableCache : false ,
75
- ScratchDir : cliScratchDir ,
65
+ ScratchDir : docker . ScratchDir ,
76
66
}
77
67
setupOpt , err := util .SetupOptionsForRepository (* repository , extraOpt )
78
68
if err != nil {
79
- return fmt .Errorf ("setup option for repository fail " )
69
+ return fmt .Errorf ("setup option for repository failed " )
80
70
}
81
- resticWrapper , err := restic .NewResticWrapper (setupOpt )
82
- if err != nil {
71
+
72
+ // write secret and config
73
+ // cleanup whole config/secret dir at the end
74
+ defer os .RemoveAll (cliSecretDir )
75
+ defer os .RemoveAll (cliConfigDir )
76
+ if err = prepareDockerVolumeForRestore (* secret , setupOpt , restoreOpt ); err != nil {
83
77
return err
84
78
}
85
- // if destination flag not specified, restore in current directory
86
- if restoreOpt .Destination == "" {
87
- restoreOpt .Destination , err = os .Getwd ()
88
- if err != nil {
89
- return err
90
- }
91
- }
92
- // run restore
93
- if _ , err = resticWrapper .RunRestore (restoreOpt ); err != nil {
79
+
80
+ // run restore inside docker
81
+ if err = runRestoreViaDocker (localDestination ); err != nil {
94
82
return err
95
83
}
96
84
log .Infof ("Repository %s/%s restored in path %s" , namespace , repositoryName , restoreOpt .Destination )
@@ -101,12 +89,65 @@ func NewDownloadCmd() *cobra.Command {
101
89
cmd .Flags ().StringVar (& kubeConfig , "kubeconfig" , kubeConfig , "Path of the Kube config file." )
102
90
cmd .Flags ().StringVar (& repositoryName , "repository" , repositoryName , "Name of the Repository." )
103
91
cmd .Flags ().StringVar (& namespace , "namespace" , "default" , "Namespace of the Repository." )
92
+ cmd .Flags ().StringVar (& localDestination , "destination" , localDestination , "Destination path where snapshot will be restored." )
104
93
105
- cmd .Flags ().StringVar (& restoreOpt .Destination , "destination" , restoreOpt .Destination , "Destination path where snapshot will be restored." )
106
94
cmd .Flags ().StringVar (& restoreOpt .SourceHost , "host" , restoreOpt .SourceHost , "Name of the source host machine" )
107
95
cmd .Flags ().StringSliceVar (& restoreOpt .RestoreDirs , "directories" , restoreOpt .RestoreDirs , "List of directories to be restored" )
108
- // TODO: only allow a single snapshot ?
109
96
cmd .Flags ().StringSliceVar (& restoreOpt .Snapshots , "snapshots" , restoreOpt .Snapshots , "List of snapshots to be restored" )
110
97
98
+ cmd .Flags ().StringVar (& image .Registry , "docker-registry" , image .Registry , "Docker image registry for unlock job" )
99
+ cmd .Flags ().StringVar (& image .Tag , "image-tag" , image .Tag , "Stash image tag for unlock job" )
100
+
111
101
return cmd
112
102
}
103
+
104
+ func prepareDockerVolumeForRestore (secret core.Secret , setupOpt restic.SetupOptions , restoreOpt restic.RestoreOptions ) error {
105
+ // write repository secrets
106
+ if err := os .MkdirAll (cliSecretDir , 0755 ); err != nil {
107
+ return err
108
+ }
109
+ for key , value := range secret .Data {
110
+ if err := ioutil .WriteFile (filepath .Join (cliSecretDir , key ), value , 0755 ); err != nil {
111
+ return err
112
+ }
113
+ }
114
+ // write restic options
115
+ err := docker .WriteSetupOptionToFile (& setupOpt , filepath .Join (cliConfigDir , docker .SetupOptionsFile ))
116
+ if err != nil {
117
+ return err
118
+ }
119
+ return docker .WriteRestoreOptionToFile (& restoreOpt , filepath .Join (cliConfigDir , docker .RestoreOptionsFile ))
120
+ }
121
+
122
+ func runRestoreViaDocker (localDestination string ) error {
123
+ // get current user
124
+ currentUser , err := user .Current ()
125
+ if err != nil {
126
+ return err
127
+ }
128
+ // if destination flag is not specified, restore in current directory
129
+ if localDestination == "" {
130
+ if localDestination , err = os .Getwd (); err != nil {
131
+ return err
132
+ }
133
+ }
134
+ // create local destination dir
135
+ if err := os .MkdirAll (localDestination , 0755 ); err != nil {
136
+ return err
137
+ }
138
+ args := []string {
139
+ "run" ,
140
+ "--rm" ,
141
+ "-u" , currentUser .Uid ,
142
+ "-v" , cliConfigDir + ":" + docker .ConfigDir ,
143
+ "-v" , cliSecretDir + ":" + docker .SecretDir ,
144
+ "-v" , localDestination + ":" + docker .DestinationDir ,
145
+ image .ToContainerImage (),
146
+ "docker" ,
147
+ "download-snapshots" ,
148
+ }
149
+ log .Infoln ("Running docker with args:" , args )
150
+ out , err := exec .Command ("docker" , args ... ).CombinedOutput ()
151
+ log .Infoln ("Output:" , string (out ))
152
+ return err
153
+ }
0 commit comments