backup_minister 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/backup_minister +28 -2
- data/lib/backup_minister.rb +11 -0
- data/lib/backup_minister/agent.rb +64 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b944e992d64bd98fe8c5843d9a061a063ce2d159
|
4
|
+
data.tar.gz: e2c999388a8ce746da8be7398fc81d9c4f8c85b4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 788d174df306e30204ac0535aab390d815c14b8946473d8d8bf1eef9de322a6156bc75a7ec2a2a67d85baa5370b960db1019295833e117c9b6107cbfb9b50500
|
7
|
+
data.tar.gz: 0a1eef9e35f4b30d3ba6e9f058d412baa7f5e98ec7348ba64feb45e51b5f3c5da9fba7da1560fd5b2a7d98300efc47dda0b1552f7402e1d61aaca2a757fadeb3
|
data/bin/backup_minister
CHANGED
@@ -3,12 +3,38 @@ require 'backup_minister'
|
|
3
3
|
require 'thor'
|
4
4
|
|
5
5
|
class CLI < Thor
|
6
|
+
desc 'backup_database', 'Backup DB and place it one remote server.'
|
7
|
+
option :project_name, type: :string, required: true, aliases: :name
|
8
|
+
def backup_database
|
9
|
+
agent = BackupMinister::Agent.new
|
10
|
+
backup_file_path = agent.backup_database(options[:project_name])
|
11
|
+
if backup_file_path
|
12
|
+
digest = agent.file_sha256_hash(backup_file_path)
|
13
|
+
placed_file_path = agent.place_database_backup(backup_file_path)
|
14
|
+
if agent.process_remote_database_backup(options[:project_name], placed_file_path, digest)
|
15
|
+
LOGGER.info "Database for project #{options[:project_name]} placed on remote server."
|
16
|
+
else
|
17
|
+
LOGGER.error "Could not place database backup for project #{options[:project_name]} on remote server."
|
18
|
+
exit!(true)
|
19
|
+
end
|
20
|
+
else
|
21
|
+
LOGGER.error "Could not create database backup for project #{options[:project_name]}."
|
22
|
+
exit!(true)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
6
26
|
desc 'backup_database', 'Move database TAR GZ archive to destination directory'
|
7
27
|
option :project_name, type: :string, required: true, aliases: :name
|
8
28
|
option :file, type: :string, required: true, banner: '</Path/to/database/backup.tar.gz>'
|
9
|
-
|
29
|
+
option :sha256, type: :string, banner: 'Hash of uploaded file'
|
30
|
+
def store_database_backup
|
10
31
|
server = BackupMinister::Server.new
|
11
|
-
server.place_database_backup(options[:project_name], options[:file])
|
32
|
+
if server.place_database_backup(options[:project_name], options[:file])
|
33
|
+
LOGGER.info "Database for project #{options[:project_name]} backed up."
|
34
|
+
else
|
35
|
+
LOGGER.error "Could not complete backup #{options[:project_name]}."
|
36
|
+
exit!(true)
|
37
|
+
end
|
12
38
|
end
|
13
39
|
|
14
40
|
desc 'sync_path', 'Server\'s path for files'
|
data/lib/backup_minister.rb
CHANGED
@@ -2,6 +2,7 @@ require 'net/ssh'
|
|
2
2
|
require 'open3'
|
3
3
|
require 'logger'
|
4
4
|
require 'fileutils'
|
5
|
+
require 'digest'
|
5
6
|
|
6
7
|
LOGGER = Logger.new(STDOUT)
|
7
8
|
APP_NAME = 'backup_minister'
|
@@ -87,6 +88,16 @@ class BackupMinister
|
|
87
88
|
out
|
88
89
|
end
|
89
90
|
|
91
|
+
# Get SHA256 Hash of file
|
92
|
+
#
|
93
|
+
# @param file_path [String] path to file
|
94
|
+
#
|
95
|
+
# @return [String, nil]
|
96
|
+
def file_sha256_hash(file_path)
|
97
|
+
file = File.read(file_path)
|
98
|
+
Digest::SHA256.hexdigest(file) if file
|
99
|
+
end
|
100
|
+
|
90
101
|
private
|
91
102
|
|
92
103
|
attr_accessor :config
|
@@ -8,6 +8,7 @@ DATABASE_DRIVERS = %i(docker)
|
|
8
8
|
class BackupMinister::Agent < BackupMinister
|
9
9
|
@projects = nil
|
10
10
|
@config_file_name = nil
|
11
|
+
@remote_server_connection = nil
|
11
12
|
|
12
13
|
def initialize(file_name = nil)
|
13
14
|
super
|
@@ -68,7 +69,7 @@ class BackupMinister::Agent < BackupMinister
|
|
68
69
|
LOGGER.info "Connection with server #{user}@#{host} established."
|
69
70
|
|
70
71
|
remote_install = connection.exec!("gem list -i #{APP_NAME}")
|
71
|
-
if remote_install == 'true'
|
72
|
+
if remote_install.to_s.strip == 'true'
|
72
73
|
LOGGER.debug "#{APP_NAME} installed on remote server."
|
73
74
|
result = true
|
74
75
|
else
|
@@ -150,6 +151,45 @@ class BackupMinister::Agent < BackupMinister
|
|
150
151
|
result
|
151
152
|
end
|
152
153
|
|
154
|
+
# Move database backup to server
|
155
|
+
#
|
156
|
+
# @return [String, nil] path to backup on remote server
|
157
|
+
def place_database_backup(file_path)
|
158
|
+
result = nil
|
159
|
+
destination_directory = '/tmp/'
|
160
|
+
scp_command = "scp #{file_path} #{system_config('server', 'user')}@#{system_config('server', 'host')}:#{destination_directory}"
|
161
|
+
if execute(scp_command)
|
162
|
+
LOGGER.debug "Backup #{file_path} placed remotely to #{destination_directory}."
|
163
|
+
|
164
|
+
FileUtils.rm(file_path)
|
165
|
+
LOGGER.debug "Local file #{file_path} removed."
|
166
|
+
|
167
|
+
result = destination_directory + File.basename(file_path)
|
168
|
+
else
|
169
|
+
LOGGER.error "Could not move #{file_path} to server."
|
170
|
+
end
|
171
|
+
result
|
172
|
+
end
|
173
|
+
|
174
|
+
# Execute command on remote server for processing database backup
|
175
|
+
#
|
176
|
+
# @param project_name [String]
|
177
|
+
# @param remote_file_path [String]
|
178
|
+
# @param sha256 [String, nil]
|
179
|
+
#
|
180
|
+
# @return [Bool] is operation success?
|
181
|
+
def process_remote_database_backup(project_name, remote_file_path, sha256 = nil)
|
182
|
+
result = false
|
183
|
+
command = "#{APP_NAME} store_database_backup"
|
184
|
+
command += " --project_name=#{project_name}"
|
185
|
+
command += " --file=#{remote_file_path}"
|
186
|
+
command += " --sha256=#{sha256}" unless sha256.nil?
|
187
|
+
|
188
|
+
execute_remotely { result = (@remote_server_connection.exec!(command).exitstatus == 0) }
|
189
|
+
|
190
|
+
result
|
191
|
+
end
|
192
|
+
|
153
193
|
# Create TAR GZ single file archive
|
154
194
|
#
|
155
195
|
# @param file_name [String] file name for new archive (including extension)
|
@@ -195,4 +235,27 @@ class BackupMinister::Agent < BackupMinister
|
|
195
235
|
nil
|
196
236
|
end
|
197
237
|
end
|
238
|
+
|
239
|
+
def remote_server_connect
|
240
|
+
if check_server_requirements
|
241
|
+
begin
|
242
|
+
host = system_config('server', 'host')
|
243
|
+
user = system_config('server', 'user')
|
244
|
+
|
245
|
+
@remote_server_connection = Net::SSH.start(host, user)
|
246
|
+
rescue Exception => error
|
247
|
+
LOGGER.error "Could not establish connection: #{error.message}"
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
def remote_server_close_connection
|
253
|
+
@remote_server_connection.close if !@remote_server_connection.nil? and !@remote_server_connection.closed?
|
254
|
+
end
|
255
|
+
|
256
|
+
def execute_remotely
|
257
|
+
remote_server_connect
|
258
|
+
yield if block_given?
|
259
|
+
remote_server_close_connection
|
260
|
+
end
|
198
261
|
end
|