backup_minister 0.0.1 → 0.0.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: af89f01465c72c52b25a8e609c50519a15fe6ab6
4
- data.tar.gz: 62c62db31e310a4e6b22abdab8bfb69c2732f69f
3
+ metadata.gz: b944e992d64bd98fe8c5843d9a061a063ce2d159
4
+ data.tar.gz: e2c999388a8ce746da8be7398fc81d9c4f8c85b4
5
5
  SHA512:
6
- metadata.gz: 411b3d4bcb3c1a841d7440f5bc8d3904fc26b7da9afce45feee939116c4e9b5b51259a79d16a95e1df3a39b0225e0bce8437470b53d9b3cde5557ea6dcd65204
7
- data.tar.gz: 1bd6a245ba4a09435506db87cf257251ebe873bdbd897a63136452d18114f480dc9219f10902f5fb11fcf0eed571928528bbe48436a7a71db7c2f841ec5d1185
6
+ metadata.gz: 788d174df306e30204ac0535aab390d815c14b8946473d8d8bf1eef9de322a6156bc75a7ec2a2a67d85baa5370b960db1019295833e117c9b6107cbfb9b50500
7
+ data.tar.gz: 0a1eef9e35f4b30d3ba6e9f058d412baa7f5e98ec7348ba64feb45e51b5f3c5da9fba7da1560fd5b2a7d98300efc47dda0b1552f7402e1d61aaca2a757fadeb3
@@ -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
- def backup_database
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'
@@ -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
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: backup_minister
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ilya Krigouzov