postgresinator 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,3 @@
1
+ standby_mode = 'on'
2
+ primary_conninfo = 'host=<%= @server.master_ip %> port=<%= @server.master_port %> user=replicator password=yourpassword sslmode=require'
3
+ trigger_file = '<%= @cluster.image.data_path %>/postgresql.trigger'
@@ -0,0 +1,523 @@
1
+ require 'erb'
2
+
3
+ require './postgresinator.rb'
4
+
5
+ ## NOTES:
6
+ # tasks without 'desc' description lines are for manual debugging of this
7
+ # deployment code.
8
+ #
9
+ # postgrestinator does not currently support more than one master or
10
+ # slave per domain for a particular cluster configuration file, but
11
+ # that can be accomplished with multiple postgresinator.rb configs.
12
+ #
13
+ # we've choosen to only pass strings (if anything) to tasks. this allows tasks to be
14
+ # debugged individually. only private methods take ruby objects.
15
+
16
+ namespace :pg do
17
+
18
+ task :ensure_setup => ['config:load_settings', 'config:ensure_cluster_data_uniqueness'] do |t, args|
19
+ # use 'rake pg:COMMAND debug=true' for debugging (you can also add --trace if you like)
20
+ SSHKit.config.output_verbosity = Logger::DEBUG if ENV['debug'] == "true"
21
+ Rake::Task['config:config_file_not_found'].invoke(args.config_file) unless args.config_file.nil?
22
+ Rake::Task['config:database_not_found'].invoke(args.database_name) unless args.database_name.nil?
23
+ Rake::Task['config:domain_not_found'].invoke(args.domain) unless args.domain.nil?
24
+ Rake::Task['config:role_not_found'].invoke(args.role_name) unless(args.role_name.nil? or args.force == "true")
25
+ end
26
+
27
+ desc "Idempotently setup one or more PostgreSQL instances using values in ./postgresinator.rb"
28
+ task :setup => :ensure_setup do
29
+ # instance variables are lost inside SSHKit's 'on' block, so
30
+ # at the beginning of each task we assign @cluster to cluster.
31
+ cluster = @cluster
32
+ cluster.servers.each do |server|
33
+ Rake::Task['pg:ensure_access_docker'].invoke(server.domain)
34
+ Rake::Task['pg:ensure_access_docker'].reenable
35
+ Rake::Task['pg:open_firewall'].invoke(server.domain)
36
+ Rake::Task['pg:open_firewall'].reenable
37
+ # 'on', 'run_locally', 'as', 'execute', 'info', 'warn', and 'fatal' are from SSHKit
38
+ on "#{cluster.ssh_user}@#{server.domain}" do
39
+ config_file_changed = false
40
+ cluster.image.config_files.each do |config_file|
41
+ next if config_file == "recovery.conf"
42
+ if config_file_differs?(cluster, server, config_file)
43
+ warn "Config file #{config_file} on #{server.domain} is being updated."
44
+ Rake::Task['pg:install_config_file'].invoke(server.domain, config_file)
45
+ Rake::Task['pg:install_config_file'].reenable
46
+ config_file_changed = true
47
+ end
48
+ end
49
+ unless container_exists?(server)
50
+ # the create_container task's prerequisite task :ensure_config_files is
51
+ # for manual use of create_container, so here we clear_prerequisites.
52
+ Rake::Task['pg:create_container'].clear_prerequisites
53
+ Rake::Task['pg:create_container'].invoke(server.domain)
54
+ Rake::Task['pg:create_container'].reenable
55
+ else
56
+ unless container_is_running?(server)
57
+ Rake::Task['pg:start_container'].invoke(server.domain)
58
+ Rake::Task['pg:start_container'].reenable
59
+ else
60
+ if config_file_changed
61
+ Rake::Task['pg:restart_container'].invoke(server.domain)
62
+ Rake::Task['pg:restart_container'].reenable
63
+ else
64
+ info "No config file changes for #{server.container_name} and it is already running; we're setup!"
65
+ end
66
+ end
67
+ end
68
+ # sleep to allow postgres to start up before running subsequent commands against it
69
+ sleep 3
70
+ if server.master
71
+ unless role_exists?(cluster, server, "replicator")
72
+ info "Creating role 'replicator' #{server.domain}"
73
+ Rake::Task['pg:create_role'].invoke(server.domain, "replicator")
74
+ Rake::Task['pg:create_role'].reenable
75
+ end
76
+ cluster.databases.each do |database|
77
+ unless role_exists?(cluster, server, database.role)
78
+ info "Creating role #{database.role} on #{server.domain}"
79
+ Rake::Task['pg:create_role'].invoke(server.domain, database.role)
80
+ Rake::Task['pg:create_role'].reenable
81
+ end
82
+ unless database_exists?(cluster, server, database)
83
+ info "Creating database #{database.name} on #{server.domain}"
84
+ Rake::Task['pg:create_database'].invoke(server.domain, database.name)
85
+ Rake::Task['pg:create_database'].reenable
86
+ Rake::Task['pg:grant_database'].invoke(server.domain, database.name)
87
+ Rake::Task['pg:grant_database'].reenable
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
94
+
95
+ desc "Check the statuses of each PostgreSQL instance in the cluster."
96
+ task :statuses => :ensure_setup do
97
+ cluster = @cluster
98
+ cluster.servers.each do |server|
99
+ Rake::Task['pg:status'].invoke(server.domain)
100
+ Rake::Task['pg:status'].reenable
101
+ end
102
+ end
103
+
104
+ desc "Check the status of the PostgreSQL instance on 'domain'."
105
+ task :status, [:domain] => :ensure_setup do |t, args|
106
+ cluster = @cluster
107
+ server = cluster.servers.select { |s| s.domain == args.domain }.first
108
+ on "#{cluster.ssh_user}@#{server.domain}" do
109
+ if container_exists?(server)
110
+ info "#{server.container_name} exists on #{server.domain}"
111
+ if container_is_running?(server)
112
+ info ""
113
+ info "#{server.container_name} is running on #{server.domain}"
114
+ info ""
115
+ Rake::Task['pg:list_roles'].invoke(server.domain)
116
+ Rake::Task['pg:list_roles'].reenable
117
+ info ""
118
+ Rake::Task['pg:list_databases'].invoke(server.domain)
119
+ Rake::Task['pg:list_databases'].reenable
120
+ info ""
121
+ Rake::Task['pg:streaming_status'].invoke(server.domain)
122
+ Rake::Task['pg:streaming_status'].reenable
123
+ else
124
+ info "#{server.container_name} is not running on #{server.domain}"
125
+ end
126
+ else
127
+ info "#{server.container_name} does not exist on #{server.domain}"
128
+ end
129
+ end
130
+ end
131
+
132
+ desc "Restore 'dump_file' in /tmp on the master server into 'database_name'."
133
+ task :restore, [:dump_file, :database_name] => :ensure_setup do |t, args|
134
+ cluster = @cluster
135
+ database = cluster.databases.select { |d| d.name == args.database_name }.first
136
+ # we only restore on the master server
137
+ server = cluster.servers.select { |s| s.master }.first
138
+ on "#{cluster.ssh_user}@#{server.domain}" do
139
+ if server.master
140
+ clean = ""
141
+ unless database_empty?(cluster, server, database)
142
+ if confirm_database_overwrite?(server, database); clean = "--clean"; else exit(0); end
143
+ end
144
+ execute("docker", "run", "--rm",
145
+ "--volume", "/tmp:/tmp:rw",
146
+ "--entrypoint", "/bin/bash",
147
+ "--volumes-from", server.container_name,
148
+ cluster.image.name,
149
+ "-c", "'/usr/bin/pg_restore", "-U", "postgres", clean,
150
+ "-d", database.name, "-F", "tar", "-v", "/tmp/#{args.dump_file}'"
151
+ )
152
+ end
153
+ end
154
+ end
155
+
156
+ desc "Dump 'database_name' into /tmp/'dump_file' on the master server."
157
+ task :dump, [:dump_file, :database_name] => :ensure_setup do |t, args|
158
+ cluster = @cluster
159
+ database = cluster.databases.select { |d| d.name == args.database_name }.first
160
+ # we only dump from the master server
161
+ server = cluster.servers.select { |s| s.master }.first
162
+ on "#{cluster.ssh_user}@#{server.domain}" do
163
+ if server.master
164
+ confirm_file_overwrite?(server, args.dump_file) if file_exists?("/tmp/#{args.dump_file}")
165
+ execute("docker", "run", "--rm",
166
+ "--volume", "/tmp:/tmp:rw",
167
+ "--entrypoint", "/bin/bash",
168
+ "--volumes-from", server.container_name,
169
+ cluster.image.name,
170
+ "-c", "'/usr/bin/pg_dump", "-U", "postgres", "-F", "tar",
171
+ "-v", database.name, ">", "/tmp/#{args.dump_file}'"
172
+ )
173
+ end
174
+ end
175
+ end
176
+
177
+ desc "Print the command to enter psql interactive mode on 'domain'."
178
+ task :print_interactive, [:domain] => :ensure_setup do |t, args|
179
+ cluster = @cluster
180
+ server = cluster.servers.select { |s| s.domain == args.domain }.first
181
+ run_locally do
182
+ info "You can paste the following command into a terminal on #{server.domain} to enter psql interactive mode for #{server.container_name}:"
183
+ info "docker run --rm --interactive --tty --volumes-from #{server.container_name} --entrypoint /bin/bash #{cluster.image.name} -lic '/usr/bin/psql -U postgres'"
184
+ end
185
+ end
186
+
187
+ task :ensure_config_files, [:domain] => :ensure_setup do |t, args|
188
+ cluster = @cluster
189
+ server = cluster.servers.select { |s| s.domain == args.domain }.first
190
+ on "#{cluster.ssh_user}@#{server.domain}" do
191
+ cluster.image.config_files.each do |config_file|
192
+ next if config_file == "recovery.conf"
193
+ if config_file_differs?(cluster, server, config_file)
194
+ Rake::Task['pg:install_config_file'].invoke(server.domain, config_file)
195
+ Rake::Task['pg:install_config_file'].reenable
196
+ end
197
+ end
198
+ end
199
+ end
200
+
201
+ task :create_container, [:domain] => :ensure_config_files do |t, args|
202
+ cluster = @cluster
203
+ server = cluster.servers.select { |s| s.domain == args.domain }.first
204
+ master_server = cluster.servers.select { |s| s.master }.first
205
+ unless server.master
206
+ on "#{cluster.ssh_user}@#{master_server.domain}" do
207
+ fatal "Master must be running before creating a slave" and raise unless container_is_running?(master_server)
208
+ end
209
+ end
210
+ on "#{cluster.ssh_user}@#{server.domain}" do
211
+ warn "Starting a new container named #{server.container_name} on #{server.domain}"
212
+ as 'root' do
213
+ fatal_message = "#{server.data_path} on #{server.domain} is not empty, cannot continue! " +
214
+ "You'll need to delete those files by hand. Be sure you are not deleting important data!"
215
+ fatal fatal_message and raise if files_in_data_path?(server)
216
+ execute("mkdir", "-p", server.data_path) unless test("test", "-d", server.data_path)
217
+ execute("chown", "-R", "#{cluster.image.postgres_uid}:#{cluster.image.postgres_gid}", server.data_path)
218
+ execute("chmod", "700", server.data_path)
219
+ execute("docker", "run", server.docker_init_command)
220
+ unless server.master
221
+ execute("rm", "#{server.data_path}/*", "-rf")
222
+ execute("docker", "run", server.docker_replicate_command)
223
+ Rake::Task['pg:link_keys'].invoke(server.domain)
224
+ Rake::Task['pg:link_keys'].reenable
225
+ Rake::Task['pg:install_config_file'].invoke(server.domain, "recovery.conf")
226
+ Rake::Task['pg:install_config_file'].reenable
227
+ end
228
+ execute("docker", "run", server.docker_run_command)
229
+ end
230
+ end
231
+ end
232
+
233
+ task :restart_container, [:domain] => :ensure_setup do |t, args|
234
+ cluster = @cluster
235
+ server = cluster.servers.select { |s| s.domain == args.domain }.first
236
+ on "#{cluster.ssh_user}@#{server.domain}" do
237
+ warn "Restarting a running container named #{server.container_name}"
238
+ execute("docker", "restart", server.container_name)
239
+ sleep 2
240
+ fatal stay_running_message(server) and raise unless container_is_running?(server)
241
+ end
242
+ end
243
+
244
+ task :start_container, [:domain] => :ensure_setup do |t, args|
245
+ cluster = @cluster
246
+ server = cluster.servers.select { |s| s.domain == args.domain }.first
247
+ on "#{cluster.ssh_user}@#{server.domain}" do
248
+ warn "Starting an existing but non-running container named #{server.container_name}"
249
+ execute("docker", "start", server.container_name)
250
+ sleep 2
251
+ fatal stay_running_message(server) and raise unless container_is_running?(server)
252
+ end
253
+ end
254
+
255
+ task :ensure_access_docker, [:domain] => :ensure_setup do |t, args|
256
+ cluster = @cluster
257
+ on "#{cluster.ssh_user}@#{args.domain}" do
258
+ as cluster.ssh_user do
259
+ unless test("bash", "-c", "\"docker", "ps", "&>", "/dev/null\"")
260
+ execute("sudo", "usermod", "-a", "-G", "docker", cluster.ssh_user)
261
+ fatal "Newly added to docker group, this run will fail, next run will succeed. Simply try again."
262
+ end
263
+ end
264
+ end
265
+ end
266
+
267
+ task :install_config_file, [:domain, :config_file] => :ensure_setup do |t, args|
268
+ cluster = @cluster
269
+ server = cluster.servers.select { |s| s.domain == args.domain }.first
270
+ on "#{cluster.ssh_user}@#{args.domain}" do
271
+ as 'root' do
272
+ # TODO: get this recovery.conf dependancy out of here?
273
+ path = args.config_file == "recovery.conf" ? server.data_path : server.conf_path
274
+ execute("mkdir", "-p", path) unless test("test", "-d", path)
275
+ generated_config_file = generate_config_file(cluster, server, args.config_file)
276
+ upload! StringIO.new(generated_config_file), "/tmp/#{args.config_file}"
277
+ execute("mv", "/tmp/#{args.config_file}", "#{path}/#{args.config_file}")
278
+ execute("chown", "-R", "#{cluster.image.postgres_uid}:#{cluster.image.postgres_gid}", path)
279
+ execute("chmod", "700", path)
280
+ end
281
+ end
282
+ end
283
+
284
+ task :list_roles, [:domain] => :ensure_setup do |t, args|
285
+ cluster = @cluster
286
+ server = cluster.servers.select { |s| s.domain == args.domain }.first
287
+ on "#{cluster.ssh_user}@#{args.domain}" do
288
+ capture("docker", "run", "--rm",
289
+ "--entrypoint", "/bin/bash",
290
+ "--volumes-from", server.container_name,
291
+ cluster.image.name,
292
+ "-c", "'/usr/bin/psql", "-U", "postgres",
293
+ "-c", "\"\\du\"'").each_line { |line| info line }
294
+ end
295
+ end
296
+
297
+ task :list_databases, [:domain] => :ensure_setup do |t, args|
298
+ cluster = @cluster
299
+ server = cluster.servers.select { |s| s.domain == args.domain }.first
300
+ on "#{cluster.ssh_user}@#{args.domain}" do
301
+ capture("docker", "run", "--rm",
302
+ "--entrypoint", "/bin/bash",
303
+ "--volumes-from", server.container_name,
304
+ cluster.image.name,
305
+ "-c", "'/usr/bin/psql", "-U", "postgres",
306
+ "-a", "-c", "\"\\l\"'").each_line { |line| info line }
307
+ end
308
+ end
309
+
310
+ task :streaming_status, [:domain] => :ensure_setup do |t, args|
311
+ cluster = @cluster
312
+ server = cluster.servers.select { |s| s.domain == args.domain }.first
313
+ on "#{cluster.ssh_user}@#{args.domain}" do
314
+ if server.master
315
+ info "Streaming status of #{server.container_name} on #{server.domain}:"
316
+ capture("echo", "\"SELECT", "*", "FROM", "pg_stat_replication;\"", "|",
317
+ "docker", "run", "--rm", "--interactive",
318
+ "--entrypoint", "/bin/bash",
319
+ "--volumes-from", server.container_name,
320
+ cluster.image.name,
321
+ "-c", "'/usr/bin/psql", "-U", "postgres", "-xa'").each_line { |line| info line }
322
+ else
323
+ # TODO: fix this for slave servers
324
+ info "Streaming status of #{server.container_name} on #{server.domain}:"
325
+ capture("echo", "\"SELECT", "now()", "-", "pg_last_xact_replay_timestamp()",
326
+ "AS", "replication_delay;\"", "|",
327
+ "docker", "run", "--rm", "--interactive",
328
+ "--entrypoint", "/bin/bash",
329
+ "--volumes-from", server.container_name,
330
+ cluster.image.name,
331
+ "-c", "'/usr/bin/psql", "-U", "postgres'").each_line { |line| info line }
332
+ end
333
+ end
334
+ end
335
+
336
+ task :create_role, [:domain, :role_name, :force] => :ensure_setup do |t, args|
337
+ args.with_defaults :force => "false"
338
+ cluster = @cluster
339
+ server = cluster.servers.select { |s| s.domain == args.domain }.first
340
+ on "#{cluster.ssh_user}@#{args.domain}" do
341
+ execute("echo", "\"CREATE", "ROLE", "\\\"#{args.role_name}\\\"",
342
+ "WITH", "LOGIN", "ENCRYPTED", "PASSWORD", "'#{args.role_name}'",
343
+ "REPLICATION", "CREATEDB;\"", "|",
344
+ "docker", "run", "--rm", "--interactive",
345
+ "--entrypoint", "/bin/bash",
346
+ "--volumes-from", server.container_name,
347
+ cluster.image.name,
348
+ "-c", "'/usr/bin/psql", "-U", "postgres'")
349
+ end
350
+ end
351
+
352
+ task :create_database, [:domain, :database_name] => :ensure_setup do |t, args|
353
+ cluster = @cluster
354
+ database = cluster.databases.select { |d| d.name == args.database_name }.first
355
+ server = cluster.servers.select { |s| s.domain == args.domain }.first
356
+ on "#{cluster.ssh_user}@#{args.domain}" do
357
+ execute("echo", "\"CREATE", "DATABASE", "\\\"#{database.name}\\\"",
358
+ "WITH", "OWNER", "\\\"#{database.role}\\\"", "TEMPLATE",
359
+ "template0", "ENCODING", "'UTF8';\"", "|",
360
+ "docker", "run", "--rm", "--interactive",
361
+ "--entrypoint", "/bin/bash",
362
+ "--volumes-from", server.container_name,
363
+ cluster.image.name,
364
+ "-c", "'/usr/bin/psql", "-U", "postgres'")
365
+ end
366
+ end
367
+
368
+ task :grant_database, [:domain, :database_name] => :ensure_setup do |t, args|
369
+ cluster = @cluster
370
+ database = cluster.databases.select { |d| d.name == args.database_name }.first
371
+ server = cluster.servers.select { |s| s.domain == args.domain }.first
372
+ on "#{cluster.ssh_user}@#{args.domain}" do
373
+ execute("echo", "\"GRANT", "ALL", "PRIVILEGES", "ON", "DATABASE",
374
+ "\\\"#{database.name}\\\"", "to", "\\\"#{database.role}\\\";\"", "|",
375
+ "docker", "run", "--rm", "--interactive",
376
+ "--entrypoint", "/bin/bash",
377
+ "--volumes-from", server.container_name,
378
+ cluster.image.name,
379
+ "-c", "'/usr/bin/psql", "-U", "postgres'")
380
+ end
381
+ end
382
+
383
+ task :link_keys, [:domain] => :ensure_setup do |t, args|
384
+ cluster = @cluster
385
+ server = cluster.servers.select { |s| s.domain == args.domain }.first
386
+ on "#{cluster.ssh_user}@#{args.domain}" do
387
+ as "root" do
388
+ inner_server_crt = "#{cluster.image.data_path}/server.crt"
389
+ outer_server_crt = "#{server.data_path}/server.crt"
390
+ unless file_exists?(outer_server_crt)
391
+ execute("docker", "run",
392
+ "--rm", "--user", "root", "--entrypoint", "/bin/ln",
393
+ "--volume", "#{server.data_path}:#{cluster.image.data_path}:rw",
394
+ cluster.image.name, "-s", "/etc/ssl/certs/ssl-cert-snakeoil.pem", inner_server_crt
395
+ )
396
+ execute("chown", "root.", outer_server_crt)
397
+ end
398
+ inner_server_key = "#{cluster.image.data_path}/server.key"
399
+ outer_server_key = "#{server.data_path}/server.key"
400
+ unless file_exists?(outer_server_key)
401
+ execute("docker", "run",
402
+ "--rm", "--user", "root", "--entrypoint", "/bin/ln",
403
+ "--volume", "#{server.data_path}:#{cluster.image.data_path}:rw",
404
+ cluster.image.name, "-s", "/etc/ssl/private/ssl-cert-snakeoil.key", inner_server_key
405
+ )
406
+ execute("chown", "root.", outer_server_key)
407
+ end
408
+ end
409
+ end
410
+ end
411
+
412
+ task :open_firewall, [:domain] => :ensure_setup do |t, args|
413
+ cluster = @cluster
414
+ server = cluster.servers.select { |s| s.domain == args.domain }.first
415
+ on "#{cluster.ssh_user}@#{args.domain}" do
416
+ as "root" do
417
+ if test "ufw", "status"
418
+ raise "Error during opening UFW firewall" unless test("ufw", "allow", "#{server.port}/tcp")
419
+ end
420
+ end
421
+ end
422
+ end
423
+
424
+ private
425
+
426
+ def stay_running_message(server)
427
+ "Container #{server.container_name} on #{server.domain} did not stay running more than 2 seconds"
428
+ end
429
+
430
+ def files_in_data_path?(server)
431
+ test("[", "\"$(ls", "-A", "#{server.data_path})\"", "]")
432
+ end
433
+
434
+ def config_file_differs?(cluster, server, config_file)
435
+ generated_config_file = generate_config_file(cluster, server, config_file)
436
+ as 'root' do
437
+ if file_exists?("#{server.conf_path}/#{config_file}")
438
+ capture("cat", "#{server.conf_path}/#{config_file}").chomp != generated_config_file.chomp
439
+ else
440
+ true
441
+ end
442
+ end
443
+ end
444
+
445
+ def generate_config_file(cluster, server, config_file)
446
+ @cluster = cluster # needed for ERB
447
+ @server = server # needed for ERB
448
+ template_path = File.expand_path("templates/#{config_file}.erb")
449
+ ERB.new(File.new(template_path).read).result(binding)
450
+ end
451
+
452
+ def role_exists?(cluster, server, role)
453
+ test("echo", "\"SELECT", "*", "FROM", "pg_user", "WHERE", "usename", "=", "'#{role}';\"", "|",
454
+ "docker", "run", "--rm", "--interactive",
455
+ "--entrypoint", "/bin/bash",
456
+ "--volumes-from", server.container_name,
457
+ cluster.image.name,
458
+ "-c", "'/usr/bin/psql", "-U", "postgres'", "|",
459
+ "grep", "-q", "'#{role}'")
460
+ end
461
+
462
+ def database_exists?(cluster, server, database)
463
+ test "docker", "run", "--rm",
464
+ "--entrypoint", "/bin/bash",
465
+ "--volumes-from", server.container_name,
466
+ cluster.image.name,
467
+ "-c", "'/usr/bin/psql", "-U", "postgres", "-lqt", "|",
468
+ "cut", "-d\\|", "-f1", "|", "grep", "-w", "#{database.name}'"
469
+ end
470
+
471
+ def container_exists?(server)
472
+ test "docker", "inspect", server.container_name, ">", "/dev/null"
473
+ end
474
+
475
+ def container_is_running?(server)
476
+ (capture "docker", "inspect",
477
+ "--format='{{.State.Running}}'",
478
+ server.container_name).strip == "true"
479
+ end
480
+
481
+ def file_exists?(file_name_path)
482
+ test "[", "-f", file_name_path, "]"
483
+ end
484
+
485
+ def confirm_file_overwrite?(server, dump_file)
486
+ warn "A file named #{dump_file} already exists on #{server.domain} in /tmp. If you continue, you will overwrite it."
487
+ warn "Are you positive(Y/N)?"
488
+ STDOUT.flush
489
+ case STDIN.gets.chomp.upcase
490
+ when "Y"
491
+ true
492
+ when "N"
493
+ false
494
+ else
495
+ warn "Please enter Y or N"
496
+ confirm_file_overwrite?(server, dump_file)
497
+ end
498
+ end
499
+
500
+ def confirm_database_overwrite?(server, database)
501
+ warn "There is already data in #{database.name} on #{server.domain} in the container " +
502
+ "#{server.container_name} which stores it's data in #{server.data_path} on the host."
503
+ warn "If you continue, you must be positive you want to overwrite the existing data."
504
+ warn "Are you positive(Y/N)?"
505
+ STDOUT.flush
506
+ case STDIN.gets.chomp.upcase
507
+ when "Y"
508
+ true
509
+ when "N"
510
+ false
511
+ else
512
+ warn "Please enter Y or N"
513
+ confirm_database_overwrite?(server, database)
514
+ end
515
+ end
516
+
517
+ def database_empty?(cluster, server, database)
518
+ test("docker", "run", "--rm", "--volumes-from", server.container_name,
519
+ "--entrypoint", "/bin/bash", cluster.image.name, "-lc",
520
+ "'/usr/bin/psql", "-U", "postgres", "-d", database.name,
521
+ "-c", "\"\\dt\"", "|", "grep", "-qi", "\"no relations found\"'")
522
+ end
523
+ end