@@ -33,10 +33,8 @@ const (
3333RestoreJobType = "logical-restore"
3434
3535// const defines restore options.
36- restoreContainerName = "retrieval_logical_restore"
37- pgDataContainerDir = "/var/lib/postgresql/pgdata"
38- dumpContainerFile = "/tmp/db.dump"
39- defaultParallelJobs = 1
36+ restoreContainerPrefix = "dblab_lr_"
37+ defaultParallelJobs = 1
4038)
4139
4240// RestoreJob defines a logical restore job.
@@ -80,10 +78,6 @@ func NewJob(cfg config.JobConfig, docker *client.Client, globalCfg *dblabCfg.Glo
8078
8179restoreJob .setDefaults ()
8280
83- if err := restoreJob .dbMarker .CreateConfig ();err != nil {
84- return nil ,errors .Wrap (err ,"failed to create a DBMarker config of the database" )
85- }
86-
8781return restoreJob ,nil
8882}
8983
@@ -94,32 +88,41 @@ func (r *RestoreJob) setDefaults() {
9488}
9589}
9690
91+ func (r * RestoreJob )restoreContainerName ()string {
92+ return restoreContainerPrefix + r .globalCfg .InstanceID
93+ }
94+
9795// Name returns a name of the job.
9896func (r * RestoreJob )Name ()string {
9997return r .name
10098}
10199
102100// Run starts the job.
103- func (r * RestoreJob )Run (ctx context.Context )error {
101+ func (r * RestoreJob )Run (ctx context.Context )( err error ) {
104102log .Msg (fmt .Sprintf ("Run job: %s. Options: %v" ,r .Name (),r .RestoreOptions ))
105103
106104isEmpty ,err := tools .IsEmptyDirectory (r .globalCfg .DataDir )
107105if err != nil {
108- return errors .Wrap (err ,"failed to explore the data directory" )
106+ return errors .Wrapf (err ,"failed to explore the data directory %q" , r . globalCfg . DataDir )
109107}
110108
111109if ! isEmpty {
112110if ! r .ForceInit {
113- return errors .New ("the data directory is not empty. Use 'forceInit' or empty the data directory" )
111+ return errors .Errorf ("the data directory %q is not empty. Use 'forceInit' or empty the data directory" ,
112+ r .globalCfg .DataDir )
114113}
115114
116- log .Msg ("The data directory is not empty. Existing data may be overwritten." )
115+ log .Msg (fmt .Sprintf ("The data directory %q is not empty. Existing data may be overwritten." ,r .globalCfg .DataDir ))
116+ }
117+
118+ if err := tools .PullImage (ctx ,r .dockerClient ,r .RestoreOptions .DockerImage );err != nil {
119+ return errors .Wrap (err ,"failed to scan image pulling response" )
117120}
118121
119122cont ,err := r .dockerClient .ContainerCreate (ctx ,
120123& container.Config {
121124Env : []string {
122- "PGDATA=" + pgDataContainerDir ,
125+ "PGDATA=" + r . globalCfg . DataDir ,
123126},
124127Image :r .RestoreOptions .DockerImage ,
125128Healthcheck :health .GetConfig (),
@@ -129,29 +132,35 @@ func (r *RestoreJob) Run(ctx context.Context) error {
129132{
130133Type :mount .TypeBind ,
131134Source :r .RestoreOptions .DumpFile ,
132- Target :dumpContainerFile ,
135+ Target :r . RestoreOptions . DumpFile ,
133136},
134137{
135138Type :mount .TypeBind ,
136139Source :r .globalCfg .DataDir ,
137- Target :pgDataContainerDir ,
140+ Target :r . globalCfg . DataDir ,
138141},
139142},
140143},
141144& network.NetworkingConfig {},
142- restoreContainerName ,
145+ r . restoreContainerName () ,
143146)
144147if err != nil {
145- return errors .Wrap (err ,"failed to create container" )
148+ return errors .Wrapf (err ,"failed to create container %q" , r . restoreContainerName () )
146149}
147150
148151defer tools .RemoveContainer (ctx ,r .dockerClient ,cont .ID ,tools .StopTimeout )
149152
153+ defer func () {
154+ if err != nil {
155+ tools .PrintContainerLogs (ctx ,r .dockerClient ,r .restoreContainerName ())
156+ }
157+ }()
158+
150159if err := r .dockerClient .ContainerStart (ctx ,cont .ID , types.ContainerStartOptions {});err != nil {
151- return errors .Wrap (err ,"failed to starta container" )
160+ return errors .Wrapf (err ,"failed to start container %q" , r . restoreContainerName () )
152161}
153162
154- log .Msg (fmt .Sprintf ("Running container: %s. ID: %v" ,restoreContainerName ,cont .ID ))
163+ log .Msg (fmt .Sprintf ("Running container: %s. ID: %v" ,r . restoreContainerName () ,cont .ID ))
155164
156165if err := r .markDatabase (ctx ,cont .ID );err != nil {
157166return errors .Wrap (err ,"failed to mark the database" )
@@ -172,19 +181,19 @@ func (r *RestoreJob) Run(ctx context.Context) error {
172181})
173182
174183if err != nil {
175- return errors .Wrap (err ,"failed to createan exec command" )
184+ return errors .Wrap (err ,"failed to createrestore command" )
176185}
177186
178187if len (r .Partial .Tables )> 0 {
179188log .Msg ("Partial restore will be run. Tables for restoring: " ,strings .Join (r .Partial .Tables ,", " ))
180189}
181190
182191if err := r .dockerClient .ContainerExecStart (ctx ,execCommand .ID , types.ExecStartCheck {Tty :true });err != nil {
183- return errors .Wrap (err ,"failed to runthe exec command" )
192+ return errors .Wrap (err ,"failed to runrestore command" )
184193}
185194
186195if err := tools .InspectCommandResponse (ctx ,r .dockerClient ,cont .ID ,execCommand .ID );err != nil {
187- return errors .Wrap (err ,"failed to execthe restore command" )
196+ return errors .Wrap (err ,"failed to exec restore command" )
188197}
189198
190199if err := recalculateStats (ctx ,r .dockerClient ,cont .ID ,buildAnalyzeCommand (Connection {
@@ -209,6 +218,10 @@ func (r *RestoreJob) markDatabase(ctx context.Context, contID string) error {
209218r .dbMark .DataStateAt = dataStateAt
210219}
211220
221+ if err := r .dbMarker .CreateConfig ();err != nil {
222+ return errors .Wrap (err ,"failed to create a DBMarker config of the database" )
223+ }
224+
212225if err := r .dbMarker .SaveConfig (r .dbMark );err != nil {
213226return errors .Wrap (err ,"failed to mark the database" )
214227}
@@ -217,20 +230,22 @@ func (r *RestoreJob) markDatabase(ctx context.Context, contID string) error {
217230}
218231
219232func (r * RestoreJob )retrieveDataStateAt (ctx context.Context ,contID string ) (string ,error ) {
220- restoreMetaCmd := []string {"sh" ,"-c" ,"pg_restore -l " + dumpContainerFile + " | head -n 10" }
233+ restoreMetaCmd := []string {"sh" ,"-c" ,"pg_restore -l " + r .RestoreOptions .DumpFile + " | head -n 10" }
234+
235+ log .Dbg ("Running a restore metadata command: " ,restoreMetaCmd )
221236
222237execCommand ,err := r .dockerClient .ContainerExecCreate (ctx ,contID , types.ExecConfig {
223238AttachStdout :true ,
224239AttachStderr :true ,
225240Cmd :restoreMetaCmd ,
226241})
227242if err != nil {
228- return "" ,errors .Wrap (err ,"failed to create a restoremeta command" )
243+ return "" ,errors .Wrap (err ,"failed to create a restoremetadata command" )
229244}
230245
231246execAttach ,err := r .dockerClient .ContainerExecAttach (ctx ,execCommand .ID , types.ExecStartCheck {})
232247if err != nil {
233- return "" ,errors .Wrap (err ,"failed to exec a restoremeta command" )
248+ return "" ,errors .Wrap (err ,"failed to exec a restoremetadata command" )
234249}
235250
236251defer execAttach .Close ()
@@ -258,7 +273,7 @@ func (r *RestoreJob) buildLogicalRestoreCommand() []string {
258273restoreCmd = append (restoreCmd ,"-t" ,table )
259274}
260275
261- restoreCmd = append (restoreCmd ,dumpContainerFile )
276+ restoreCmd = append (restoreCmd ,r . RestoreOptions . DumpFile )
262277
263278return restoreCmd
264279}