pg_export 0.6.1 → 0.7.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.
- 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
|