pg_export 0.6.1 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.rubocop.yml +9 -13
- data/.travis.yml +2 -2
- data/CHANGELOG.md +9 -0
- data/Gemfile +2 -0
- data/README.md +28 -29
- data/Rakefile +2 -0
- data/bin/console +2 -8
- data/bin/pg_export +44 -45
- data/lib/pg_export/build_logger.rb +4 -2
- data/lib/pg_export/configuration.rb +22 -2
- data/lib/pg_export/container.rb +48 -0
- data/lib/pg_export/import.rb +7 -0
- data/lib/pg_export/lib/pg_export/adapters/bash_adapter.rb +37 -0
- data/lib/pg_export/lib/pg_export/adapters/ftp_adapter.rb +67 -0
- data/lib/pg_export/lib/pg_export/entities/dump.rb +45 -0
- data/lib/pg_export/lib/pg_export/factories/cipher_factory.rb +32 -0
- data/lib/pg_export/lib/pg_export/factories/dump_factory.rb +31 -0
- data/lib/pg_export/lib/pg_export/factories/ftp_adapter_factory.rb +22 -0
- data/lib/pg_export/lib/pg_export/listeners/interactive/build_dump.rb +19 -0
- data/lib/pg_export/lib/pg_export/listeners/interactive/close_ftp_connection.rb +19 -0
- data/lib/pg_export/lib/pg_export/listeners/interactive/decrypt_dump.rb +19 -0
- data/lib/pg_export/lib/pg_export/listeners/interactive/download_dump_from_ftp.rb +19 -0
- data/lib/pg_export/lib/pg_export/listeners/interactive/encrypt_dump.rb +19 -0
- data/lib/pg_export/lib/pg_export/listeners/interactive/fetch_dumps_from_ftp.rb +19 -0
- data/lib/pg_export/lib/pg_export/listeners/interactive/open_ftp_connection.rb +19 -0
- data/lib/pg_export/lib/pg_export/listeners/interactive/remove_old_dumps_from_ftp.rb +23 -0
- data/lib/pg_export/lib/pg_export/listeners/interactive/restore.rb +19 -0
- data/lib/pg_export/lib/pg_export/listeners/interactive/upload_dump_to_ftp.rb +19 -0
- data/lib/pg_export/lib/pg_export/listeners/interactive_listener.rb +49 -0
- data/lib/pg_export/lib/pg_export/listeners/plain/build_dump.rb +15 -0
- data/lib/pg_export/lib/pg_export/listeners/plain/close_ftp_connection.rb +15 -0
- data/lib/pg_export/lib/pg_export/listeners/plain/decrypt_dump.rb +15 -0
- data/lib/pg_export/lib/pg_export/listeners/plain/download_dump_from_ftp.rb +15 -0
- data/lib/pg_export/lib/pg_export/listeners/plain/encrypt_dump.rb +15 -0
- data/lib/pg_export/lib/pg_export/listeners/plain/fetch_dumps_from_ftp.rb +15 -0
- data/lib/pg_export/lib/pg_export/listeners/plain/open_ftp_connection.rb +15 -0
- data/lib/pg_export/lib/pg_export/listeners/plain/remove_old_dumps_from_ftp.rb +17 -0
- data/lib/pg_export/lib/pg_export/listeners/plain/restore.rb +15 -0
- data/lib/pg_export/lib/pg_export/listeners/plain/upload_dump_to_ftp.rb +15 -0
- data/lib/pg_export/lib/pg_export/listeners/plain_listener.rb +17 -0
- data/lib/pg_export/lib/pg_export/operations/decrypt_dump.rb +20 -0
- data/lib/pg_export/lib/pg_export/operations/encrypt_dump.rb +18 -0
- data/lib/pg_export/lib/pg_export/operations/open_ftp_connection.rb +19 -0
- data/lib/pg_export/lib/pg_export/operations/remove_old_dumps_from_ftp.rb +22 -0
- data/lib/pg_export/lib/pg_export/repositories/ftp_dump_file_repository.rb +19 -0
- data/lib/pg_export/lib/pg_export/repositories/ftp_dump_repository.rb +36 -0
- data/lib/pg_export/lib/pg_export/transactions/export_dump.rb +56 -0
- data/lib/pg_export/lib/pg_export/transactions/import_dump_interactively.rb +67 -0
- data/lib/pg_export/lib/pg_export/types.rb +14 -0
- data/lib/pg_export/lib/pg_export/ui/interactive/input.rb +36 -0
- data/lib/pg_export/lib/pg_export/ui/plain/input.rb +17 -0
- data/lib/pg_export/lib/pg_export/value_objects/dump_file.rb +70 -0
- data/lib/pg_export/system/boot/config.rb +11 -0
- data/lib/pg_export/system/boot/interactive.rb +32 -0
- data/lib/pg_export/system/boot/logger.rb +15 -0
- data/lib/pg_export/system/boot/plain.rb +33 -0
- data/lib/pg_export/version.rb +3 -1
- data/lib/pg_export.rb +23 -20
- data/pg_export.gemspec +13 -10
- metadata +108 -52
- data/lib/pg_export/aes/base.rb +0 -47
- data/lib/pg_export/aes/decryptor.rb +0 -13
- data/lib/pg_export/aes/encryptor.rb +0 -13
- data/lib/pg_export/aes.rb +0 -3
- data/lib/pg_export/bash/adapter.rb +0 -31
- data/lib/pg_export/bash/factory.rb +0 -23
- data/lib/pg_export/bash/repository.rb +0 -18
- data/lib/pg_export/boot_container.rb +0 -69
- data/lib/pg_export/dump.rb +0 -62
- data/lib/pg_export/errors.rb +0 -5
- data/lib/pg_export/ftp/adapter.rb +0 -41
- data/lib/pg_export/ftp/connection.rb +0 -40
- data/lib/pg_export/ftp/repository.rb +0 -40
- data/lib/pg_export/roles/colourable_string.rb +0 -19
- data/lib/pg_export/roles/human_readable.rb +0 -17
- data/lib/pg_export/roles/interactive.rb +0 -98
- data/lib/pg_export/roles/validatable.rb +0 -24
- data/lib/pg_export/services/create_and_export_dump.rb +0 -20
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# auto_register: false
|
4
|
+
|
5
|
+
require 'pg_export/lib/pg_export/adapters/ftp_adapter'
|
6
|
+
require 'pg_export/import'
|
7
|
+
|
8
|
+
class PgExport
|
9
|
+
module Factories
|
10
|
+
class FtpAdapterFactory
|
11
|
+
include Import['config']
|
12
|
+
|
13
|
+
def ftp_adapter
|
14
|
+
::PgExport::Adapters::FtpAdapter.new(
|
15
|
+
host: config.ftp_host,
|
16
|
+
user: config.ftp_user,
|
17
|
+
password: config.ftp_password
|
18
|
+
)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../interactive_listener'
|
4
|
+
|
5
|
+
class PgExport
|
6
|
+
module Listeners
|
7
|
+
class Interactive
|
8
|
+
class BuildDump < InteractiveListener
|
9
|
+
def on_step(step_name:, args:)
|
10
|
+
@spinner = build_spinner("Dumping database #{args.first[:database_name]}")
|
11
|
+
end
|
12
|
+
|
13
|
+
def on_step_succeeded(step_name:, args:, value:)
|
14
|
+
@spinner.success([success, value[:dump]].join(' '))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../interactive_listener'
|
4
|
+
|
5
|
+
class PgExport
|
6
|
+
module Listeners
|
7
|
+
class Interactive
|
8
|
+
class CloseFtpConnection < InteractiveListener
|
9
|
+
def on_step(*)
|
10
|
+
@spinner = build_spinner('Closing FTP')
|
11
|
+
end
|
12
|
+
|
13
|
+
def on_step_succeeded(*)
|
14
|
+
@spinner.success(success)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../interactive_listener'
|
4
|
+
|
5
|
+
class PgExport
|
6
|
+
module Listeners
|
7
|
+
class Interactive
|
8
|
+
class DecryptDump < InteractiveListener
|
9
|
+
def on_step(*)
|
10
|
+
@spinner = build_spinner('Decrypting')
|
11
|
+
end
|
12
|
+
|
13
|
+
def on_step_succeeded(step_name:, args:, value:)
|
14
|
+
@spinner.success([success, value[:dump]].join(' '))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../interactive_listener'
|
4
|
+
|
5
|
+
class PgExport
|
6
|
+
module Listeners
|
7
|
+
class Interactive
|
8
|
+
class DownloadDumpFromFtp < InteractiveListener
|
9
|
+
def on_step(*)
|
10
|
+
@spinner = build_spinner('Downloading')
|
11
|
+
end
|
12
|
+
|
13
|
+
def on_step_succeeded(step_name:, args:, value:)
|
14
|
+
@spinner.success([success, value[:dump]].join(' '))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../interactive_listener'
|
4
|
+
|
5
|
+
class PgExport
|
6
|
+
module Listeners
|
7
|
+
class Interactive
|
8
|
+
class EncryptDump < InteractiveListener
|
9
|
+
def on_step(*)
|
10
|
+
@spinner = build_spinner('Encrypting')
|
11
|
+
end
|
12
|
+
|
13
|
+
def on_step_succeeded(step_name:, args:, value:)
|
14
|
+
@spinner.success([success, value[:dump]].join(' '))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../interactive_listener'
|
4
|
+
|
5
|
+
class PgExport
|
6
|
+
module Listeners
|
7
|
+
class Interactive
|
8
|
+
class FetchDumpsFromFtp < InteractiveListener
|
9
|
+
def on_step(*)
|
10
|
+
@spinner = build_spinner('Fetching dumps')
|
11
|
+
end
|
12
|
+
|
13
|
+
def on_step_succeeded(*)
|
14
|
+
@spinner.success(success)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../interactive_listener'
|
4
|
+
|
5
|
+
class PgExport
|
6
|
+
module Listeners
|
7
|
+
class Interactive
|
8
|
+
class OpenFtpConnection < InteractiveListener
|
9
|
+
def on_step(*)
|
10
|
+
@spinner = build_spinner('Opening ftp connection')
|
11
|
+
end
|
12
|
+
|
13
|
+
def on_step_succeeded(*)
|
14
|
+
@spinner.success(success)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../interactive_listener'
|
4
|
+
|
5
|
+
class PgExport
|
6
|
+
module Listeners
|
7
|
+
class Interactive
|
8
|
+
class RemoveOldDumpsFromFtp < InteractiveListener
|
9
|
+
def on_step(step_name:, args:)
|
10
|
+
@spinner = build_spinner("Checking for old dumps on #{args.first[:ftp_adapter]}")
|
11
|
+
end
|
12
|
+
|
13
|
+
def on_step_succeeded(step_name:, args:, value:)
|
14
|
+
if value[:removed_dumps].any?
|
15
|
+
@spinner.success([success, value[:removed_dumps].map { |filename| " #{filename} removed" }].join("\n"))
|
16
|
+
else
|
17
|
+
@spinner.success([success, 'nothing to remove'].join(' '))
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../interactive_listener'
|
4
|
+
|
5
|
+
class PgExport
|
6
|
+
module Listeners
|
7
|
+
class Interactive
|
8
|
+
class Restore < InteractiveListener
|
9
|
+
def on_step(step_name:, args:)
|
10
|
+
@spinner = build_spinner("Restoring dump to database #{args.first[:database]}")
|
11
|
+
end
|
12
|
+
|
13
|
+
def on_step_succeeded(*)
|
14
|
+
@spinner.success(success)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../interactive_listener'
|
4
|
+
|
5
|
+
class PgExport
|
6
|
+
module Listeners
|
7
|
+
class Interactive
|
8
|
+
class UploadDumpToFtp < InteractiveListener
|
9
|
+
def on_step(step_name:, args:)
|
10
|
+
@spinner = build_spinner("Uploading #{args.first[:dump]} to #{args.first[:ftp_adapter]}")
|
11
|
+
end
|
12
|
+
|
13
|
+
def on_step_succeeded(*)
|
14
|
+
@spinner.success(success)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# auto_register: false
|
4
|
+
|
5
|
+
require 'pg_export/import'
|
6
|
+
require 'tty-spinner'
|
7
|
+
|
8
|
+
class PgExport
|
9
|
+
module Listeners
|
10
|
+
class InteractiveListener
|
11
|
+
def on_step_failed(step_name:, args:, value:)
|
12
|
+
@spinner.error([error, self.class.red(value[:message])].join("\n"))
|
13
|
+
end
|
14
|
+
|
15
|
+
class << self
|
16
|
+
def green(s)
|
17
|
+
"\e[0;32;49m#{s}\e[0m"
|
18
|
+
end
|
19
|
+
|
20
|
+
def red(s)
|
21
|
+
"\e[31m#{s}\e[0m"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
SUCCESS_MARK = green("\u2713").freeze
|
28
|
+
ERROR_MARK = red("\u00d7").freeze
|
29
|
+
private_constant :SUCCESS_MARK, :ERROR_MARK
|
30
|
+
|
31
|
+
def build_spinner(message)
|
32
|
+
TTY::Spinner.new(
|
33
|
+
"[:spinner] #{message}...",
|
34
|
+
format: :dots,
|
35
|
+
success_mark: SUCCESS_MARK,
|
36
|
+
error_mark: ERROR_MARK
|
37
|
+
).tap(&:auto_spin)
|
38
|
+
end
|
39
|
+
|
40
|
+
def success
|
41
|
+
self.class.green('(success)')
|
42
|
+
end
|
43
|
+
|
44
|
+
def error
|
45
|
+
self.class.red('(error)')
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../plain_listener'
|
4
|
+
|
5
|
+
class PgExport
|
6
|
+
module Listeners
|
7
|
+
class Plain
|
8
|
+
class BuildDump < PlainListener
|
9
|
+
def on_step_succeeded(step_name:, args:, value:)
|
10
|
+
logger.info("Dump database #{value[:dump].database} to #{value[:dump]}")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../plain_listener'
|
4
|
+
|
5
|
+
class PgExport
|
6
|
+
module Listeners
|
7
|
+
class Plain
|
8
|
+
class CloseFtpConnection < PlainListener
|
9
|
+
def on_step_succeeded(*)
|
10
|
+
logger.info('Close FTP')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../plain_listener'
|
4
|
+
|
5
|
+
class PgExport
|
6
|
+
module Listeners
|
7
|
+
class Plain
|
8
|
+
class DecryptDump < PlainListener
|
9
|
+
def on_step_succeeded(step_name:, args:, value:)
|
10
|
+
logger.info("Decrypt #{value[:dump]}")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../plain_listener'
|
4
|
+
|
5
|
+
class PgExport
|
6
|
+
module Listeners
|
7
|
+
class Plain
|
8
|
+
class DownloadDumpFromFtp < PlainListener
|
9
|
+
def on_step_succeeded(step_name:, args:, value:)
|
10
|
+
logger.info("Download #{value[:dump]}")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../plain_listener'
|
4
|
+
|
5
|
+
class PgExport
|
6
|
+
module Listeners
|
7
|
+
class Plain
|
8
|
+
class EncryptDump < PlainListener
|
9
|
+
def on_step_succeeded(step_name:, args:, value:)
|
10
|
+
logger.info("Encrypt #{value[:dump]}")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../plain_listener'
|
4
|
+
|
5
|
+
class PgExport
|
6
|
+
module Listeners
|
7
|
+
class Plain
|
8
|
+
class FetchDumpsFromFtp < PlainListener
|
9
|
+
def on_step_succeeded(step_name:, args:, value:)
|
10
|
+
logger.info("Fetch dumps (#{value[:dumps].count} items)")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../plain_listener'
|
4
|
+
|
5
|
+
class PgExport
|
6
|
+
module Listeners
|
7
|
+
class Plain
|
8
|
+
class OpenFtpConnection < PlainListener
|
9
|
+
def on_step_succeeded(step_name:, args:, value:)
|
10
|
+
logger.info("Connect to #{value[:ftp_adapter]}")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../plain_listener'
|
4
|
+
|
5
|
+
class PgExport
|
6
|
+
module Listeners
|
7
|
+
class Plain
|
8
|
+
class RemoveOldDumpsFromFtp < PlainListener
|
9
|
+
def on_step_succeeded(step_name:, args:, value:)
|
10
|
+
value[:removed_dumps].each do |filename|
|
11
|
+
logger.info("Remove #{filename} from #{value[:ftp_adapter]}")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../plain_listener'
|
4
|
+
|
5
|
+
class PgExport
|
6
|
+
module Listeners
|
7
|
+
class Plain
|
8
|
+
class Restore < PlainListener
|
9
|
+
def on_step_succeeded(step_name:, args:, value:)
|
10
|
+
logger.info("Restore dump to database #{args.first[:database]}")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../plain_listener'
|
4
|
+
|
5
|
+
class PgExport
|
6
|
+
module Listeners
|
7
|
+
class Plain
|
8
|
+
class UploadDumpToFtp < PlainListener
|
9
|
+
def on_step_succeeded(step_name:, args:, value:)
|
10
|
+
logger.info("Upload #{value[:dump]} to #{value[:ftp_adapter]}")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# auto_register: false
|
4
|
+
|
5
|
+
require 'pg_export/import'
|
6
|
+
|
7
|
+
class PgExport
|
8
|
+
module Listeners
|
9
|
+
class PlainListener
|
10
|
+
include Import['logger']
|
11
|
+
|
12
|
+
def on_step_failed(step_name:, args:, value:)
|
13
|
+
logger.info("Error: #{value[:message]}")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'dry/transaction/operation'
|
4
|
+
require 'pg_export/import'
|
5
|
+
|
6
|
+
class PgExport
|
7
|
+
module Operations
|
8
|
+
class DecryptDump
|
9
|
+
include Dry::Transaction::Operation
|
10
|
+
include Import['factories.cipher_factory']
|
11
|
+
|
12
|
+
def call(dump:)
|
13
|
+
dump.decrypt(cipher_factory: cipher_factory)
|
14
|
+
Success(dump: dump)
|
15
|
+
rescue OpenSSL::Cipher::CipherError => e
|
16
|
+
Failure(message: "Problem decrypting dump file: #{e}. Try again.")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'dry/transaction/operation'
|
4
|
+
require 'pg_export/import'
|
5
|
+
|
6
|
+
class PgExport
|
7
|
+
module Operations
|
8
|
+
class EncryptDump
|
9
|
+
include Dry::Transaction::Operation
|
10
|
+
include Import['factories.cipher_factory']
|
11
|
+
|
12
|
+
def call(dump:)
|
13
|
+
dump.encrypt(cipher_factory: cipher_factory)
|
14
|
+
Success(dump: dump)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'dry/transaction/operation'
|
4
|
+
require 'pg_export/import'
|
5
|
+
|
6
|
+
class PgExport
|
7
|
+
module Operations
|
8
|
+
class OpenFtpConnection
|
9
|
+
include Dry::Transaction::Operation
|
10
|
+
include Import['factories.ftp_adapter_factory']
|
11
|
+
|
12
|
+
def call(inputs)
|
13
|
+
ftp_adapter = ftp_adapter_factory.ftp_adapter
|
14
|
+
ftp_adapter.open_ftp
|
15
|
+
Success(inputs.merge(ftp_adapter: ftp_adapter))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'dry/transaction/operation'
|
4
|
+
require 'pg_export/import'
|
5
|
+
|
6
|
+
class PgExport
|
7
|
+
module Operations
|
8
|
+
class RemoveOldDumpsFromFtp
|
9
|
+
include Dry::Transaction::Operation
|
10
|
+
include Import['repositories.ftp_dump_repository', 'config']
|
11
|
+
|
12
|
+
def call(dump:, ftp_adapter:)
|
13
|
+
dumps = ftp_adapter.list(dump.database + '_*').drop(config.keep_dumps)
|
14
|
+
dumps.each do |filename|
|
15
|
+
ftp_adapter.delete(filename)
|
16
|
+
end
|
17
|
+
|
18
|
+
Success(removed_dumps: dumps, ftp_adapter: ftp_adapter)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'open3'
|
4
|
+
require 'pg_export/import'
|
5
|
+
require 'pg_export/lib/pg_export/entities/dump'
|
6
|
+
require 'pg_export/lib/pg_export/value_objects/dump_file'
|
7
|
+
|
8
|
+
class PgExport
|
9
|
+
module Repositories
|
10
|
+
class FtpDumpFileRepository
|
11
|
+
def by_name(name:, ftp_adapter:)
|
12
|
+
file = ValueObjects::DumpFile.new
|
13
|
+
ftp_adapter.get(file, name)
|
14
|
+
|
15
|
+
file
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'open3'
|
4
|
+
require 'pg_export/import'
|
5
|
+
require 'pg_export/lib/pg_export/entities/dump'
|
6
|
+
require 'pg_export/lib/pg_export/value_objects/dump_file'
|
7
|
+
|
8
|
+
class PgExport
|
9
|
+
module Repositories
|
10
|
+
class FtpDumpRepository
|
11
|
+
def all(database_name:, ftp_adapter:)
|
12
|
+
ftp_adapter.list([database_name, '*'].compact.join('_')).map do |name:, size:|
|
13
|
+
begin
|
14
|
+
dump(name, database_name, size)
|
15
|
+
rescue Dry::Types::ConstraintError
|
16
|
+
nil
|
17
|
+
end
|
18
|
+
end.compact
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
FilePlaceholder = Struct.new(:size)
|
24
|
+
private_constant :FilePlaceholder
|
25
|
+
|
26
|
+
def dump(name, database_name, size)
|
27
|
+
Entities::Dump.new(
|
28
|
+
name: name,
|
29
|
+
database: database_name,
|
30
|
+
file: ValueObjects::DumpFile.new(FilePlaceholder.new(size.to_i)),
|
31
|
+
type: :encrypted
|
32
|
+
)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# auto_register: false
|
4
|
+
|
5
|
+
require 'dry/transaction'
|
6
|
+
|
7
|
+
require 'pg_export/import'
|
8
|
+
require 'pg_export/container'
|
9
|
+
require 'pg_export/lib/pg_export/value_objects/dump_file'
|
10
|
+
|
11
|
+
class PgExport
|
12
|
+
module Transactions
|
13
|
+
class ExportDump
|
14
|
+
include Dry::Transaction(container: PgExport::Container)
|
15
|
+
include Import['factories.dump_factory', 'adapters.bash_adapter']
|
16
|
+
|
17
|
+
step :prepare_params
|
18
|
+
step :build_dump
|
19
|
+
step :encrypt_dump, with: 'operations.encrypt_dump'
|
20
|
+
step :open_ftp_connection, with: 'operations.open_ftp_connection'
|
21
|
+
step :upload_dump_to_ftp
|
22
|
+
step :remove_old_dumps_from_ftp, with: 'operations.remove_old_dumps_from_ftp'
|
23
|
+
step :close_ftp_connection
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def prepare_params(database_name:)
|
28
|
+
database_name = database_name.to_s
|
29
|
+
|
30
|
+
return Failure(message: 'Invalid database name') if database_name.empty?
|
31
|
+
|
32
|
+
Success(database_name: database_name)
|
33
|
+
end
|
34
|
+
|
35
|
+
def build_dump(database_name:)
|
36
|
+
dump = dump_factory.plain(
|
37
|
+
database: database_name,
|
38
|
+
file: bash_adapter.pg_dump(ValueObjects::DumpFile.new, database_name)
|
39
|
+
)
|
40
|
+
Success(dump: dump)
|
41
|
+
rescue bash_adapter.class::PgDumpError => e
|
42
|
+
Failure(message: 'Unable to dump database: ' + e.to_s)
|
43
|
+
end
|
44
|
+
|
45
|
+
def upload_dump_to_ftp(dump:, ftp_adapter:)
|
46
|
+
ftp_adapter.persist(dump.file, dump.name)
|
47
|
+
Success(dump: dump, ftp_adapter: ftp_adapter)
|
48
|
+
end
|
49
|
+
|
50
|
+
def close_ftp_connection(removed_dumps:, ftp_adapter:)
|
51
|
+
ftp_adapter.close_ftp
|
52
|
+
Success(ftp_adapter: ftp_adapter)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|