backup revision 2dbc668d1e44c95db1857d3968bcde7517852bea
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa#!/usr/bin/env ruby
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa
abc834c020080fe44a1ea4e34278327e99e3e12eEugen Kuksarequire 'tmpdir.rb'
abc834c020080fe44a1ea4e34278327e99e3e12eEugen Kuksarequire 'fileutils'
abc834c020080fe44a1ea4e34278327e99e3e12eEugen Kuksarequire 'pathname'
f0264afd33a980b6584747fc8159ee950805d9e3Eugen Kuksarequire 'open3'
f0264afd33a980b6584747fc8159ee950805d9e3Eugen Kuksarequire 'pry'
f0264afd33a980b6584747fc8159ee950805d9e3Eugen Kuksarequire 'pry-byebug'
f0264afd33a980b6584747fc8159ee950805d9e3Eugen Kuksa
f0264afd33a980b6584747fc8159ee950805d9e3Eugen Kuksamodule Backup
f0264afd33a980b6584747fc8159ee950805d9e3Eugen Kuksa class Backup
f0264afd33a980b6584747fc8159ee950805d9e3Eugen Kuksa # Amount of backups that have to be there at least
0978722f6ca27f5d5f5ed4ec8400703dfe211184Eugen Kuksa BACKUPS_COUNT = 3
f0264afd33a980b6584747fc8159ee950805d9e3Eugen Kuksa # Backups are valid for 7 days
f0264afd33a980b6584747fc8159ee950805d9e3Eugen Kuksa BACKUPS_VALIDITY_TIME = 7 * 60 * 60 * 24
f0264afd33a980b6584747fc8159ee950805d9e3Eugen Kuksa
f0264afd33a980b6584747fc8159ee950805d9e3Eugen Kuksa MAINTENANCE_FILE = 'maintenance.txt'
f0264afd33a980b6584747fc8159ee950805d9e3Eugen Kuksa
f0264afd33a980b6584747fc8159ee950805d9e3Eugen Kuksa SQL_DUMP_FILE = 'ontohub_sql_dump.postgresql'
f0264afd33a980b6584747fc8159ee950805d9e3Eugen Kuksa REPOSITORY_FILE = 'ontohub_repositories.tar.gz'
f0264afd33a980b6584747fc8159ee950805d9e3Eugen Kuksa
f0264afd33a980b6584747fc8159ee950805d9e3Eugen Kuksa DATA_DIRS = %w(data/repositories data/git_daemon)
f0264afd33a980b6584747fc8159ee950805d9e3Eugen Kuksa
f0264afd33a980b6584747fc8159ee950805d9e3Eugen Kuksa attr_reader :db_name, :data_root, :backup_root, :backup_instance_dir
f0264afd33a980b6584747fc8159ee950805d9e3Eugen Kuksa attr_reader :dry_run, :verbose, :sql_dump_as_postgres_user
f0264afd33a980b6584747fc8159ee950805d9e3Eugen Kuksa
f0264afd33a980b6584747fc8159ee950805d9e3Eugen Kuksa def initialize(db_name, data_root, backup_root,
f0264afd33a980b6584747fc8159ee950805d9e3Eugen Kuksa verbose: false, dry_run: true, sql_dump_as_postgres_user: false)
f0264afd33a980b6584747fc8159ee950805d9e3Eugen Kuksa @db_name = db_name
f0264afd33a980b6584747fc8159ee950805d9e3Eugen Kuksa @data_root = Pathname.new(data_root)
f0264afd33a980b6584747fc8159ee950805d9e3Eugen Kuksa @backup_root = Pathname.new(backup_root)
f0264afd33a980b6584747fc8159ee950805d9e3Eugen Kuksa
f0264afd33a980b6584747fc8159ee950805d9e3Eugen Kuksa @dry_run = dry_run
f0264afd33a980b6584747fc8159ee950805d9e3Eugen Kuksa @verbose = verbose
f0264afd33a980b6584747fc8159ee950805d9e3Eugen Kuksa @sql_dump_as_postgres_user = sql_dump_as_postgres_user
f0264afd33a980b6584747fc8159ee950805d9e3Eugen Kuksa end
f0264afd33a980b6584747fc8159ee950805d9e3Eugen Kuksa
f0264afd33a980b6584747fc8159ee950805d9e3Eugen Kuksa def create
f0264afd33a980b6584747fc8159ee950805d9e3Eugen Kuksa enable_maintenance_mode
f0264afd33a980b6584747fc8159ee950805d9e3Eugen Kuksa initialize_backup
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa create_sql_dump
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa create_repository_archive
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa # We needed to create the directory for the script to continue later on.
28001d576e67ba46ed481c5695f1e0827ff26007Eugen Kuksa Dir.rmdir(backup_instance_dir) if dry_run
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa disable_maintenance_mode
b1fe9054ad7c7192fe4c474363247dad15963e99Eugen Kuksa puts "created backup in #{backup_instance_dir}"
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa self.class.prune(backup_root)
5efadb4662f2a63d5f5f1a5b303ab7c3371069a8Eugen Kuksa end
d89f470f7da0b9f8295d0ac0defff09884894b8bEugen Kuksa
d89f470f7da0b9f8295d0ac0defff09884894b8bEugen Kuksa def restore(backup_name)
d89f470f7da0b9f8295d0ac0defff09884894b8bEugen Kuksa enable_maintenance_mode
5efadb4662f2a63d5f5f1a5b303ab7c3371069a8Eugen Kuksa initialize_restore(backup_name)
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa restore_sql_dump
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa restore_repository_archive
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa disable_maintenance_mode
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa puts "restored backup from #{backup_instance_dir}"
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa end
a8028fd2789e323040de08827a0fe1f7d36fde2bEugen Kuksa
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa def self.prune(backup_root)
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa if !Dir.exists?(backup_root)
366ce8d807067a97613cb23d49105d8a093c5015Eugen Kuksa $stderr.puts "Nothing to prune: There is no backup directory."
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa return
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa end
366ce8d807067a97613cb23d49105d8a093c5015Eugen Kuksa now = Time.now
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa backup_dirs_allowed_to_delete(Dir.new(backup_root).entries).each do |dir|
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa backup = backup_root.join(dir)
a8028fd2789e323040de08827a0fe1f7d36fde2bEugen Kuksa if now - File.new(backup).ctime > BACKUPS_VALIDITY_TIME
a8028fd2789e323040de08827a0fe1f7d36fde2bEugen Kuksa puts "removing old backup: #{dir}"
a8028fd2789e323040de08827a0fe1f7d36fde2bEugen Kuksa FileUtils.rm_r(backup)
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa end
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa end
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa end
366ce8d807067a97613cb23d49105d8a093c5015Eugen Kuksa
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa protected
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa def new_backup_name
4ec9d8b62c3c1a001548eb0883b6f81e00c391a0Eugen Kuksa Time.now.strftime("%Y-%m-%d_%H-%M-%S")
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa end
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa def initialize_backup
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa @backup_instance_dir = backup_root.join(new_backup_name)
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa puts "FileUtils.mkdir_p #{backup_instance_dir}" if verbose
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa # Create directory even in dry run to let the script continue.
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa FileUtils.mkdir_p(backup_instance_dir)
4ec9d8b62c3c1a001548eb0883b6f81e00c391a0Eugen Kuksa end
5efadb4662f2a63d5f5f1a5b303ab7c3371069a8Eugen Kuksa
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa def create_sql_dump
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa Dir.chdir(backup_instance_dir) do
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa exec('pg_dump', pg_user_switch, '-Fc', db_name,
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa file_dest: SQL_DUMP_FILE)
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa end
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa end
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa def create_repository_archive
4ec9d8b62c3c1a001548eb0883b6f81e00c391a0Eugen Kuksa Dir.chdir(data_root.join('..')) do
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa archive_file = backup_instance_dir.join(REPOSITORY_FILE)
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa exec('tar', verbose ? '-v' : '', '-czf', archive_file.to_s,
5efadb4662f2a63d5f5f1a5b303ab7c3371069a8Eugen Kuksa *DATA_DIRS.map(&:to_s))
5efadb4662f2a63d5f5f1a5b303ab7c3371069a8Eugen Kuksa end
923d69139038e74c0936e826bbfdc8717fbbc7b3Eugen Kuksa end
5efadb4662f2a63d5f5f1a5b303ab7c3371069a8Eugen Kuksa
5efadb4662f2a63d5f5f1a5b303ab7c3371069a8Eugen Kuksa def initialize_restore(backup_name)
5efadb4662f2a63d5f5f1a5b303ab7c3371069a8Eugen Kuksa @backup_instance_dir = backup_root.join(backup_name)
5efadb4662f2a63d5f5f1a5b303ab7c3371069a8Eugen Kuksa unless Dir.exists?(backup_instance_dir)
5efadb4662f2a63d5f5f1a5b303ab7c3371069a8Eugen Kuksa $stderr.puts "Error: Backup '#{backup_name}' does not exist in #{backup_root}."
5efadb4662f2a63d5f5f1a5b303ab7c3371069a8Eugen Kuksa exit
5efadb4662f2a63d5f5f1a5b303ab7c3371069a8Eugen Kuksa end
5efadb4662f2a63d5f5f1a5b303ab7c3371069a8Eugen Kuksa end
5efadb4662f2a63d5f5f1a5b303ab7c3371069a8Eugen Kuksa
5efadb4662f2a63d5f5f1a5b303ab7c3371069a8Eugen Kuksa def restore_sql_dump
5efadb4662f2a63d5f5f1a5b303ab7c3371069a8Eugen Kuksa Dir.chdir(backup_instance_dir) do
5efadb4662f2a63d5f5f1a5b303ab7c3371069a8Eugen Kuksa exec('pg_restore', '-c', pg_user_switch, '-d', db_name, SQL_DUMP_FILE)
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa end
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa end
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa def restore_repository_archive
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa Dir.chdir(data_root.join('..')) do
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa tmpdir = Dir.mktmpdir
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa move_data_dirs_to_tmpdir(tmpdir)
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa begin
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa extract_archive
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa remove_tmpdir(tmpdir)
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa rescue => e
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa puts <<-MSG
daf3e28fff47a65b53d6fb65155301763b9f166eEugen KuksaAn error occured while restoring the repositories:
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa#{e.message}
4ec9d8b62c3c1a001548eb0883b6f81e00c391a0Eugen KuksaYou can find the pre-restore repositories at #{tmpdir}
daf3e28fff47a65b53d6fb65155301763b9f166eEugen KuksaDo something about it.
96c47a92d836bca1aca373db8664c5ec84cfc8afEugen Kuksa MSG
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa raise e
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa end
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa end
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa end
4ec9d8b62c3c1a001548eb0883b6f81e00c391a0Eugen Kuksa
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa def move_data_dirs_to_tmpdir(tmpdir)
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa puts "FileUtils.mv(#{DATA_DIRS}, #{tmpdir})" if verbose
a8028fd2789e323040de08827a0fe1f7d36fde2bEugen Kuksa FileUtils.mv(DATA_DIRS, tmpdir) unless dry_run
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa rescue Errno::EACCES
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa puts <<-MSG
daf3e28fff47a65b53d6fb65155301763b9f166eEugen KuksaAs the current user I have no access to move the repository data
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksadirectories #{DATA_DIRS.join(' ')} to a temporary directory #{tmpdir}.
daf3e28fff47a65b53d6fb65155301763b9f166eEugen KuksaThis is used as a backup for the case of an error while restoring.
daf3e28fff47a65b53d6fb65155301763b9f166eEugen KuksaTo continue, I try the command again using sudo.
4634cde5d3428bd5ab34b8212ac2f4637cdfff6fEugen Kuksa MSG
4634cde5d3428bd5ab34b8212ac2f4637cdfff6fEugen Kuksa exec('sudo', 'mv', *DATA_DIRS.map(&:to_s), tmpdir)
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa end
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa def extract_archive
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa archive_file = backup_instance_dir.join(REPOSITORY_FILE)
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa puts <<-MSG
4ec9d8b62c3c1a001548eb0883b6f81e00c391a0Eugen Kuksa
daf3e28fff47a65b53d6fb65155301763b9f166eEugen KuksaSuper user privileges are needed to reset the file permissions as
b4ac7fd47818fbcba8d344e3de41ca62e1473b94Eugen Kuksathey were before the backup. If you refuse to enter the password
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa(Crtl-C) or enter a wrong password, only the permissions will not be
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksarestored and all restored files will belong to the current user/group.
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa MSG
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa try_as_sudo_with_fallback('tar', verbose ? '-v' : '', '-xzf',
4ec9d8b62c3c1a001548eb0883b6f81e00c391a0Eugen Kuksa archive_file.to_s, *DATA_DIRS.map(&:to_s))
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa end
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa
2dbc668d1e44c95db1857d3968bcde7517852beaEugen Kuksa def remove_tmpdir(tmpdir)
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa puts "FileUtils.remove_entry(#{tmpdir})" if verbose
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa FileUtils.remove_entry(tmpdir) # even do this in dry run
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa rescue Errno::EACCES
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa puts <<-MSG
b51057b860560bf3ee454c03a121af3d5d34f482Eugen KuksaAs the current user I have no access to remove the temporary
4ec9d8b62c3c1a001548eb0883b6f81e00c391a0Eugen Kuksadirectory #{tmpdir}.
b51057b860560bf3ee454c03a121af3d5d34f482Eugen KuksaTo continue, I try the command again using sudo.
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa MSG
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa exec('sudo', 'rm', '-r', tmpdir)
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa end
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa def enable_maintenance_mode
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa puts "FileUtils.touch #{maintenance_file}" if verbose
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa FileUtils.touch maintenance_file unless dry_run
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa end
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa def disable_maintenance_mode
a8028fd2789e323040de08827a0fe1f7d36fde2bEugen Kuksa puts "FileUtils.rm #{maintenance_file}" if verbose
a8028fd2789e323040de08827a0fe1f7d36fde2bEugen Kuksa FileUtils.rm maintenance_file unless dry_run
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa end
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa
4ec9d8b62c3c1a001548eb0883b6f81e00c391a0Eugen Kuksa def exec(*args, file_dest: nil)
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa puts "[executing next command in #{Dir.getwd}]" if verbose
a8028fd2789e323040de08827a0fe1f7d36fde2bEugen Kuksa out = args.join(' ')
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa out << " > #{file_dest}" if file_dest
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa puts out if verbose
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa Subprocess.run(*args, file_dest: file_dest) unless dry_run
a8028fd2789e323040de08827a0fe1f7d36fde2bEugen Kuksa end
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa def try_as_sudo_with_fallback(*args)
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa unless exec('sudo', *args)
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa sudo_not_given_fallback(*args) # Wrong sudo password
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa end
284432981d641cf3d679841f75acbcf039d83062Eugen Kuksa rescue Exception => e
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa raise e unless e.is_a?(Interrupt) # Ctrl-C when asked for password
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa sudo_not_given_fallback(*args)
6cdc461aada609d57d50ff675d29b15378717ff2Eugen Kuksa end
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa def sudo_not_given_fallback(*args)
76f98a73426869ab54073075345686d98b6a8cafEugen Kuksa puts 'Super user privileges not granted. Trying as normal user.'
a8028fd2789e323040de08827a0fe1f7d36fde2bEugen Kuksa exec(*args)
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa end
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa def maintenance_file
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa data_root.join(MAINTENANCE_FILE)
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa end
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa def pg_user_switch
4ec9d8b62c3c1a001548eb0883b6f81e00c391a0Eugen Kuksa sql_dump_as_postgres_user ? ' -U postgres' : ''
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa end
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa def self.backup_dirs_allowed_to_delete(entries)
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa entries.reject{ |entry| %w(. ..).include?(entry) }[0..-(BACKUPS_COUNT+1)]
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa end
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa end
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa class Subprocess
4ec9d8b62c3c1a001548eb0883b6f81e00c391a0Eugen Kuksa def self.run(*args, file_dest: nil)
bacf95fddc53ab3107f380c4c816fa8072358bd9Eugen Kuksa stdin, stdout, stderr, wait_thr, io_dest = run_streaming(*args,
bacf95fddc53ab3107f380c4c816fa8072358bd9Eugen Kuksa file_dest: file_dest)
bacf95fddc53ab3107f380c4c816fa8072358bd9Eugen Kuksa exit_code = wait_thr.value # wait for the process to finish
bacf95fddc53ab3107f380c4c816fa8072358bd9Eugen Kuksa io_dest.close if io_dest
bacf95fddc53ab3107f380c4c816fa8072358bd9Eugen Kuksa
bacf95fddc53ab3107f380c4c816fa8072358bd9Eugen Kuksa [stdout.read, stderr.read, exit_code]
486df98bbf3348cfb96e93c3e499d12435880bb5Eugen Kuksa end
486df98bbf3348cfb96e93c3e499d12435880bb5Eugen Kuksa
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa def self.run_streaming(*args, file_dest: nil)
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa stdin, stdout, stderr, wait_thr = Open3.popen3(*args)
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa io_dest = nil
4ec9d8b62c3c1a001548eb0883b6f81e00c391a0Eugen Kuksa if file_dest
486df98bbf3348cfb96e93c3e499d12435880bb5Eugen Kuksa io_dest = File.open(file_dest, 'w')
486df98bbf3348cfb96e93c3e499d12435880bb5Eugen Kuksa IO.copy_stream(stdout, io_dest)
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa end
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa [stdin, stdout, stderr, wait_thr, io_dest]
96c47a92d836bca1aca373db8664c5ec84cfc8afEugen Kuksa end
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa end
28001d576e67ba46ed481c5695f1e0827ff26007Eugen Kuksaend
28001d576e67ba46ed481c5695f1e0827ff26007Eugen Kuksa
96c47a92d836bca1aca373db8664c5ec84cfc8afEugen Kuksadef data_root(rails_root)
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa File.realpath(rails_root.join('data'))
486df98bbf3348cfb96e93c3e499d12435880bb5Eugen Kuksaend
28001d576e67ba46ed481c5695f1e0827ff26007Eugen Kuksa
dd553f2f8b8abb774ba64a4fb9ebe3abea9f7f17Eugen Kuksadef on_development_system?(rails_root)
dd553f2f8b8abb774ba64a4fb9ebe3abea9f7f17Eugen Kuksa !File.symlink?(rails_root.join('data'))
28001d576e67ba46ed481c5695f1e0827ff26007Eugen Kuksaend
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa# We assume, this script runs in "RAILS_ROOT/script/".
28001d576e67ba46ed481c5695f1e0827ff26007Eugen KuksaRAILS_ROOT = Pathname.new(__FILE__).dirname.join('..')
28001d576e67ba46ed481c5695f1e0827ff26007Eugen Kuksa
b51057b860560bf3ee454c03a121af3d5d34f482Eugen KuksaDATABASE = if on_development_system?(RAILS_ROOT)
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa 'ontohub_development'
28001d576e67ba46ed481c5695f1e0827ff26007Eugen Kuksa else
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa 'ontohub'
28001d576e67ba46ed481c5695f1e0827ff26007Eugen Kuksa end
b51057b860560bf3ee454c03a121af3d5d34f482Eugen KuksaBACKUP_ROOT = if on_development_system?(RAILS_ROOT)
b51057b860560bf3ee454c03a121af3d5d34f482Eugen Kuksa RAILS_ROOT.join('tmp', 'backup')
486df98bbf3348cfb96e93c3e499d12435880bb5Eugen Kuksa else
486df98bbf3348cfb96e93c3e499d12435880bb5Eugen Kuksa File.realpath('/home/ontohub/ontohub_data_backup')
486df98bbf3348cfb96e93c3e499d12435880bb5Eugen Kuksa end
5efadb4662f2a63d5f5f1a5b303ab7c3371069a8Eugen Kuksa
6d055d16c7620b7804b6a46cb481d00b3dbb5007Eugen Kuksabackup = Backup::Backup.new(DATABASE, data_root(RAILS_ROOT), BACKUP_ROOT,
b4ac7fd47818fbcba8d344e3de41ca62e1473b94Eugen Kuksa sql_dump_as_postgres_user: on_development_system?(RAILS_ROOT),
6d055d16c7620b7804b6a46cb481d00b3dbb5007Eugen Kuksa dry_run: false, verbose: true)
6d055d16c7620b7804b6a46cb481d00b3dbb5007Eugen Kuksa
5efadb4662f2a63d5f5f1a5b303ab7c3371069a8Eugen Kuksacase ARGV.first
5efadb4662f2a63d5f5f1a5b303ab7c3371069a8Eugen Kuksawhen 'create'
5efadb4662f2a63d5f5f1a5b303ab7c3371069a8Eugen Kuksa backup.create
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksawhen 'restore'
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa if ARGV.length == 1
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa $stderr.puts 'To restore a backup, you need to specify one with the arguments'
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa $stderr.puts '"restore backup_name"'
26e23083feb1577ee4bd102bc09ca440d20548b9Eugen Kuksa exit
26e23083feb1577ee4bd102bc09ca440d20548b9Eugen Kuksa end
26e23083feb1577ee4bd102bc09ca440d20548b9Eugen Kuksa backup_name = ARGV[1]
26e23083feb1577ee4bd102bc09ca440d20548b9Eugen Kuksa backup.restore(backup_name)
26e23083feb1577ee4bd102bc09ca440d20548b9Eugen Kuksawhen 'prune'
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa Backup::Backup.prune(BACKUP_ROOT)
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksaelse
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa $stderr.puts 'unknown or missing parameter'
2da9df454152009d7a5e0d83d519aa2bc9844233Eugen Kuksa $stderr.puts 'use parameter "create" or "restore <backup_name>" or "prune"'
2da9df454152009d7a5e0d83d519aa2bc9844233Eugen Kuksa exit
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksaend
daf3e28fff47a65b53d6fb65155301763b9f166eEugen Kuksa