@@ -33,10 +33,8 @@ const (
33
33
RestoreJobType = "logical-restore"
34
34
35
35
// 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
40
38
)
41
39
42
40
// RestoreJob defines a logical restore job.
@@ -80,10 +78,6 @@ func NewJob(cfg config.JobConfig, docker *client.Client, globalCfg *dblabCfg.Glo
80
78
81
79
restoreJob .setDefaults ()
82
80
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
-
87
81
return restoreJob , nil
88
82
}
89
83
@@ -94,32 +88,41 @@ func (r *RestoreJob) setDefaults() {
94
88
}
95
89
}
96
90
91
+ func (r * RestoreJob ) restoreContainerName () string {
92
+ return restoreContainerPrefix + r .globalCfg .InstanceID
93
+ }
94
+
97
95
// Name returns a name of the job.
98
96
func (r * RestoreJob ) Name () string {
99
97
return r .name
100
98
}
101
99
102
100
// Run starts the job.
103
- func (r * RestoreJob ) Run (ctx context.Context ) error {
101
+ func (r * RestoreJob ) Run (ctx context.Context ) ( err error ) {
104
102
log .Msg (fmt .Sprintf ("Run job: %s. Options: %v" , r .Name (), r .RestoreOptions ))
105
103
106
104
isEmpty , err := tools .IsEmptyDirectory (r .globalCfg .DataDir )
107
105
if 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 )
109
107
}
110
108
111
109
if ! isEmpty {
112
110
if ! 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 )
114
113
}
115
114
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" )
117
120
}
118
121
119
122
cont , err := r .dockerClient .ContainerCreate (ctx ,
120
123
& container.Config {
121
124
Env : []string {
122
- "PGDATA=" + pgDataContainerDir ,
125
+ "PGDATA=" + r . globalCfg . DataDir ,
123
126
},
124
127
Image : r .RestoreOptions .DockerImage ,
125
128
Healthcheck : health .GetConfig (),
@@ -129,29 +132,35 @@ func (r *RestoreJob) Run(ctx context.Context) error {
129
132
{
130
133
Type : mount .TypeBind ,
131
134
Source : r .RestoreOptions .DumpFile ,
132
- Target : dumpContainerFile ,
135
+ Target : r . RestoreOptions . DumpFile ,
133
136
},
134
137
{
135
138
Type : mount .TypeBind ,
136
139
Source : r .globalCfg .DataDir ,
137
- Target : pgDataContainerDir ,
140
+ Target : r . globalCfg . DataDir ,
138
141
},
139
142
},
140
143
},
141
144
& network.NetworkingConfig {},
142
- restoreContainerName ,
145
+ r . restoreContainerName () ,
143
146
)
144
147
if err != nil {
145
- return errors .Wrap (err , "failed to create container" )
148
+ return errors .Wrapf (err , "failed to create container %q" , r . restoreContainerName () )
146
149
}
147
150
148
151
defer tools .RemoveContainer (ctx , r .dockerClient , cont .ID , tools .StopTimeout )
149
152
153
+ defer func () {
154
+ if err != nil {
155
+ tools .PrintContainerLogs (ctx , r .dockerClient , r .restoreContainerName ())
156
+ }
157
+ }()
158
+
150
159
if err := r .dockerClient .ContainerStart (ctx , cont .ID , types.ContainerStartOptions {}); err != nil {
151
- return errors .Wrap (err , "failed to start a container" )
160
+ return errors .Wrapf (err , "failed to start container %q" , r . restoreContainerName () )
152
161
}
153
162
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 ))
155
164
156
165
if err := r .markDatabase (ctx , cont .ID ); err != nil {
157
166
return errors .Wrap (err , "failed to mark the database" )
@@ -172,19 +181,19 @@ func (r *RestoreJob) Run(ctx context.Context) error {
172
181
})
173
182
174
183
if err != nil {
175
- return errors .Wrap (err , "failed to create an exec command" )
184
+ return errors .Wrap (err , "failed to create restore command" )
176
185
}
177
186
178
187
if len (r .Partial .Tables ) > 0 {
179
188
log .Msg ("Partial restore will be run. Tables for restoring: " , strings .Join (r .Partial .Tables , ", " ))
180
189
}
181
190
182
191
if err := r .dockerClient .ContainerExecStart (ctx , execCommand .ID , types.ExecStartCheck {Tty : true }); err != nil {
183
- return errors .Wrap (err , "failed to run the exec command" )
192
+ return errors .Wrap (err , "failed to run restore command" )
184
193
}
185
194
186
195
if err := tools .InspectCommandResponse (ctx , r .dockerClient , cont .ID , execCommand .ID ); err != nil {
187
- return errors .Wrap (err , "failed to exec the restore command" )
196
+ return errors .Wrap (err , "failed to exec restore command" )
188
197
}
189
198
190
199
if err := recalculateStats (ctx , r .dockerClient , cont .ID , buildAnalyzeCommand (Connection {
@@ -209,6 +218,10 @@ func (r *RestoreJob) markDatabase(ctx context.Context, contID string) error {
209
218
r .dbMark .DataStateAt = dataStateAt
210
219
}
211
220
221
+ if err := r .dbMarker .CreateConfig (); err != nil {
222
+ return errors .Wrap (err , "failed to create a DBMarker config of the database" )
223
+ }
224
+
212
225
if err := r .dbMarker .SaveConfig (r .dbMark ); err != nil {
213
226
return errors .Wrap (err , "failed to mark the database" )
214
227
}
@@ -217,20 +230,22 @@ func (r *RestoreJob) markDatabase(ctx context.Context, contID string) error {
217
230
}
218
231
219
232
func (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 )
221
236
222
237
execCommand , err := r .dockerClient .ContainerExecCreate (ctx , contID , types.ExecConfig {
223
238
AttachStdout : true ,
224
239
AttachStderr : true ,
225
240
Cmd : restoreMetaCmd ,
226
241
})
227
242
if err != nil {
228
- return "" , errors .Wrap (err , "failed to create a restore meta command" )
243
+ return "" , errors .Wrap (err , "failed to create a restore metadata command" )
229
244
}
230
245
231
246
execAttach , err := r .dockerClient .ContainerExecAttach (ctx , execCommand .ID , types.ExecStartCheck {})
232
247
if err != nil {
233
- return "" , errors .Wrap (err , "failed to exec a restore meta command" )
248
+ return "" , errors .Wrap (err , "failed to exec a restore metadata command" )
234
249
}
235
250
236
251
defer execAttach .Close ()
@@ -258,7 +273,7 @@ func (r *RestoreJob) buildLogicalRestoreCommand() []string {
258
273
restoreCmd = append (restoreCmd , "-t" , table )
259
274
}
260
275
261
- restoreCmd = append (restoreCmd , dumpContainerFile )
276
+ restoreCmd = append (restoreCmd , r . RestoreOptions . DumpFile )
262
277
263
278
return restoreCmd
264
279
}
0 commit comments