pg_export 0.7.7 → 1.0.0.rc5

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.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +6 -3
  4. data/CHANGELOG.md +11 -0
  5. data/README.md +14 -11
  6. data/bin/pg_export +92 -26
  7. data/lib/pg_export.rb +5 -13
  8. data/lib/pg_export/configuration.rb +18 -18
  9. data/lib/pg_export/container.rb +5 -30
  10. data/lib/pg_export/import.rb +1 -1
  11. data/lib/pg_export/lib/pg_export/factories/cipher_factory.rb +7 -10
  12. data/lib/pg_export/lib/pg_export/factories/ftp_gateway_factory.rb +22 -0
  13. data/lib/pg_export/lib/pg_export/factories/ssh_gateway_factory.rb +22 -0
  14. data/lib/pg_export/lib/pg_export/{adapters/ftp_adapter.rb → gateways/ftp.rb} +11 -8
  15. data/lib/pg_export/lib/pg_export/gateways/ssh.rb +83 -0
  16. data/lib/pg_export/lib/pg_export/listeners/interactive/build_dump.rb +4 -4
  17. data/lib/pg_export/lib/pg_export/listeners/interactive/{close_ftp_connection.rb → close_connection.rb} +1 -1
  18. data/lib/pg_export/lib/pg_export/listeners/interactive/decrypt_dump.rb +2 -2
  19. data/lib/pg_export/lib/pg_export/listeners/interactive/{download_dump_from_ftp.rb → download_dump.rb} +3 -3
  20. data/lib/pg_export/lib/pg_export/listeners/interactive/encrypt_dump.rb +2 -2
  21. data/lib/pg_export/lib/pg_export/listeners/interactive/{fetch_dumps_from_ftp.rb → fetch_dumps.rb} +1 -1
  22. data/lib/pg_export/lib/pg_export/listeners/interactive/{open_ftp_connection.rb → open_connection.rb} +2 -2
  23. data/lib/pg_export/lib/pg_export/listeners/interactive/{remove_old_dumps_from_ftp.rb → remove_old_dumps.rb} +6 -6
  24. data/lib/pg_export/lib/pg_export/listeners/interactive/restore.rb +2 -2
  25. data/lib/pg_export/lib/pg_export/listeners/interactive/select_database.rb +12 -0
  26. data/lib/pg_export/lib/pg_export/listeners/interactive/select_dump.rb +12 -0
  27. data/lib/pg_export/lib/pg_export/listeners/interactive/{upload_dump_to_ftp.rb → upload_dump.rb} +3 -3
  28. data/lib/pg_export/lib/pg_export/listeners/interactive_listener.rb +2 -2
  29. data/lib/pg_export/lib/pg_export/listeners/plain/build_dump.rb +2 -2
  30. data/lib/pg_export/lib/pg_export/listeners/plain/{close_ftp_connection.rb → close_connection.rb} +2 -2
  31. data/lib/pg_export/lib/pg_export/listeners/plain/decrypt_dump.rb +2 -2
  32. data/lib/pg_export/lib/pg_export/listeners/plain/{download_dump_from_ftp.rb → download_dump.rb} +3 -3
  33. data/lib/pg_export/lib/pg_export/listeners/plain/encrypt_dump.rb +2 -2
  34. data/lib/pg_export/lib/pg_export/listeners/plain/fetch_dumps.rb +15 -0
  35. data/lib/pg_export/lib/pg_export/listeners/plain/open_connection.rb +15 -0
  36. data/lib/pg_export/lib/pg_export/listeners/plain/prepare_params.rb +15 -0
  37. data/lib/pg_export/lib/pg_export/listeners/plain/remove_old_dumps.rb +17 -0
  38. data/lib/pg_export/lib/pg_export/listeners/plain/restore.rb +1 -1
  39. data/lib/pg_export/lib/pg_export/listeners/plain/upload_dump.rb +15 -0
  40. data/lib/pg_export/lib/pg_export/listeners/plain_listener.rb +2 -2
  41. data/lib/pg_export/lib/pg_export/operations/{open_ftp_connection.rb → open_connection.rb} +5 -5
  42. data/lib/pg_export/lib/pg_export/operations/{remove_old_dumps_from_ftp.rb → remove_old_dumps.rb} +7 -7
  43. data/lib/pg_export/lib/pg_export/repositories/{ftp_dump_file_repository.rb → gateway_dump_file_repository.rb} +3 -3
  44. data/lib/pg_export/lib/pg_export/repositories/{ftp_dump_repository.rb → gateway_dump_repository.rb} +7 -7
  45. data/lib/pg_export/lib/pg_export/transactions/export_dump.rb +10 -10
  46. data/lib/pg_export/lib/pg_export/transactions/import_dump_interactively.rb +19 -19
  47. data/lib/pg_export/system/boot/config.rb +17 -1
  48. data/lib/pg_export/system/boot/ftp.rb +11 -0
  49. data/lib/pg_export/system/boot/interactive.rb +4 -20
  50. data/lib/pg_export/system/boot/operations.rb +17 -0
  51. data/lib/pg_export/system/boot/plain.rb +3 -20
  52. data/lib/pg_export/system/boot/ssh.rb +11 -0
  53. data/lib/pg_export/version.rb +1 -1
  54. data/pg_export.gemspec +9 -5
  55. metadata +101 -39
  56. data/lib/pg_export/build_logger.rb +0 -21
  57. data/lib/pg_export/lib/pg_export/factories/ftp_adapter_factory.rb +0 -22
  58. data/lib/pg_export/lib/pg_export/listeners/plain/fetch_dumps_from_ftp.rb +0 -15
  59. data/lib/pg_export/lib/pg_export/listeners/plain/open_ftp_connection.rb +0 -15
  60. data/lib/pg_export/lib/pg_export/listeners/plain/remove_old_dumps_from_ftp.rb +0 -17
  61. data/lib/pg_export/lib/pg_export/listeners/plain/upload_dump_to_ftp.rb +0 -15
  62. data/lib/pg_export/system/boot/logger.rb +0 -15
@@ -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 PrepareParams < PlainListener
9
+ def on_step_succeeded(event)
10
+ logger.info("Init")
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 RemoveOldDumps < PlainListener
9
+ def on_step_succeeded(event)
10
+ event[:value][:removed_dumps].each do |filename|
11
+ logger.info("Remove #{filename} from #{event[:value][:gateway]}")
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -6,7 +6,7 @@ class PgExport
6
6
  module Listeners
7
7
  class Plain
8
8
  class Restore < PlainListener
9
- def on_step_succeeded(step_name:, args:, value:)
9
+ def on_step_succeeded(event)
10
10
  logger.info("Restore dump to database #{args.first[:database]}")
11
11
  end
12
12
  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 UploadDump < PlainListener
9
+ def on_step_succeeded(event)
10
+ logger.info("Upload #{event[:value][:dump]} to #{event[:value][:gateway]}")
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -9,8 +9,8 @@ class PgExport
9
9
  class PlainListener
10
10
  include Import['logger']
11
11
 
12
- def on_step_failed(step_name:, args:, value:)
13
- logger.info("Error: #{value[:message]}")
12
+ def on_step_failed(event)
13
+ logger.info("Error: #{event[:value][:message]}")
14
14
  end
15
15
  end
16
16
  end
@@ -5,14 +5,14 @@ require 'pg_export/import'
5
5
 
6
6
  class PgExport
7
7
  module Operations
8
- class OpenFtpConnection
8
+ class OpenConnection
9
9
  include Dry::Transaction::Operation
10
- include Import['factories.ftp_adapter_factory']
10
+ include Import['factories.gateway_factory']
11
11
 
12
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))
13
+ gateway = gateway_factory.gateway
14
+ gateway.open
15
+ Success(inputs.merge(gateway: gateway))
16
16
  end
17
17
  end
18
18
  end
@@ -5,21 +5,21 @@ require 'pg_export/import'
5
5
 
6
6
  class PgExport
7
7
  module Operations
8
- class RemoveOldDumpsFromFtp
8
+ class RemoveOldDumps
9
9
  include Dry::Transaction::Operation
10
- include Import['repositories.ftp_dump_repository', 'config']
10
+ include Import['repositories.gateway_dump_repository', 'config']
11
11
 
12
- def call(dump:, ftp_adapter:)
13
- dumps = ftp_dump_repository.by_database_name(
12
+ def call(dump:, gateway:)
13
+ dumps = gateway_dump_repository.by_database_name(
14
14
  database_name: dump.database,
15
- ftp_adapter: ftp_adapter,
15
+ gateway: gateway,
16
16
  offset: config.keep_dumps
17
17
  )
18
18
  dumps.each do |d|
19
- ftp_adapter.delete(d.name)
19
+ gateway.delete(d.name)
20
20
  end
21
21
 
22
- Success(removed_dumps: dumps, ftp_adapter: ftp_adapter)
22
+ Success(removed_dumps: dumps, gateway: gateway)
23
23
  end
24
24
  end
25
25
  end
@@ -7,10 +7,10 @@ require 'pg_export/lib/pg_export/value_objects/dump_file'
7
7
 
8
8
  class PgExport
9
9
  module Repositories
10
- class FtpDumpFileRepository
11
- def by_name(name:, ftp_adapter:)
10
+ class GatewayDumpFileRepository
11
+ def by_name(name:, gateway:)
12
12
  file = ValueObjects::DumpFile.new
13
- ftp_adapter.get(file, name)
13
+ gateway.get(file, name)
14
14
 
15
15
  file
16
16
  end
@@ -7,21 +7,21 @@ require 'pg_export/lib/pg_export/value_objects/dump_file'
7
7
 
8
8
  class PgExport
9
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:|
10
+ class GatewayDumpRepository
11
+ def all(database_name:, gateway:)
12
+ gateway.list(database_name).map do |item|
13
13
  begin
14
- dump(name, database_name, size)
14
+ dump(item[:name], database_name, item[:size])
15
15
  rescue Dry::Types::ConstraintError
16
16
  nil
17
17
  end
18
18
  end.compact
19
19
  end
20
20
 
21
- def by_database_name(database_name:, ftp_adapter:, offset:)
22
- ftp_adapter.list(database_name + '_*').drop(offset).map do |name:, size:|
21
+ def by_database_name(database_name:, gateway:, offset:)
22
+ gateway.list(database_name).drop(offset).map do |item|
23
23
  begin
24
- dump(name, database_name, size)
24
+ dump(item[:name], database_name, item[:size])
25
25
  rescue Dry::Types::ConstraintError
26
26
  nil
27
27
  end
@@ -17,10 +17,10 @@ class PgExport
17
17
  step :prepare_params
18
18
  step :build_dump
19
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
20
+ step :open_connection, with: 'operations.open_connection'
21
+ step :upload_dump
22
+ step :remove_old_dumps, with: 'operations.remove_old_dumps'
23
+ step :close_connection
24
24
 
25
25
  private
26
26
 
@@ -42,14 +42,14 @@ class PgExport
42
42
  Failure(message: 'Unable to dump database: ' + e.to_s)
43
43
  end
44
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)
45
+ def upload_dump(dump:, gateway:)
46
+ gateway.persist(dump.file, dump.name)
47
+ Success(dump: dump, gateway: gateway)
48
48
  end
49
49
 
50
- def close_ftp_connection(removed_dumps:, ftp_adapter:)
51
- ftp_adapter.close_ftp
52
- Success(ftp_adapter: ftp_adapter)
50
+ def close_connection(removed_dumps:, gateway:)
51
+ gateway.close
52
+ Success(gateway: gateway)
53
53
  end
54
54
  end
55
55
  end
@@ -12,47 +12,47 @@ class PgExport
12
12
  class ImportDumpInteractively
13
13
  include Dry::Transaction(container: PgExport::Container)
14
14
  include Import[
15
+ 'ui.interactive.input',
15
16
  'adapters.bash_adapter',
16
- 'repositories.ftp_dump_repository',
17
- 'repositories.ftp_dump_file_repository',
18
- 'ui_input'
17
+ 'repositories.gateway_dump_repository',
18
+ 'repositories.gateway_dump_file_repository'
19
19
  ]
20
20
 
21
- step :open_ftp_connection, with: 'operations.open_ftp_connection'
22
- step :fetch_dumps_from_ftp
21
+ step :open_connection, with: 'operations.open_connection'
22
+ step :fetch_dumps
23
23
  step :select_dump
24
- step :download_dump_from_ftp
25
- step :close_ftp_connection
24
+ step :download_dump
25
+ step :close_connection
26
26
  step :decrypt_dump, with: 'operations.decrypt_dump'
27
27
  step :select_database
28
28
  step :restore
29
29
 
30
30
  private
31
31
 
32
- def fetch_dumps_from_ftp(database_name:, ftp_adapter:)
33
- dumps = ftp_dump_repository.all(database_name: database_name, ftp_adapter: ftp_adapter)
32
+ def fetch_dumps(database_name:, gateway:)
33
+ dumps = gateway_dump_repository.all(database_name: database_name, gateway: gateway)
34
34
  return Failure(message: 'No dumps') if dumps.none?
35
35
 
36
- Success(ftp_adapter: ftp_adapter, dumps: dumps)
36
+ Success(gateway: gateway, dumps: dumps)
37
37
  end
38
38
 
39
- def select_dump(dumps:, ftp_adapter:)
40
- dump = ui_input.select_dump(dumps)
41
- Success(dump: dump, ftp_adapter: ftp_adapter)
39
+ def select_dump(dumps:, gateway:)
40
+ dump = input.select_dump(dumps)
41
+ Success(dump: dump, gateway: gateway)
42
42
  end
43
43
 
44
- def download_dump_from_ftp(dump:, ftp_adapter:)
45
- dump.file = ftp_dump_file_repository.by_name(name: dump.name, ftp_adapter: ftp_adapter)
46
- Success(dump: dump, ftp_adapter: ftp_adapter)
44
+ def download_dump(dump:, gateway:)
45
+ dump.file = gateway_dump_file_repository.by_name(name: dump.name, gateway: gateway)
46
+ Success(dump: dump, gateway: gateway)
47
47
  end
48
48
 
49
- def close_ftp_connection(dump:, ftp_adapter:)
50
- Thread.new { ftp_adapter.close_ftp }
49
+ def close_connection(dump:, gateway:)
50
+ Thread.new { gateway.close }
51
51
  Success(dump: dump)
52
52
  end
53
53
 
54
54
  def select_database(dump:)
55
- name = ui_input.enter_database_name(dump.database)
55
+ name = input.enter_database_name(dump.database)
56
56
  Success(dump: dump, database: name)
57
57
  end
58
58
 
@@ -2,10 +2,26 @@
2
2
 
3
3
  PgExport::Container.boot :config do
4
4
  init do
5
+ require 'logger'
6
+ require 'pg_export/lib/pg_export/types'
5
7
  require 'pg_export/configuration'
6
8
  end
7
9
 
8
10
  start do
9
- register(:config, memoize: true) { PgExport::Configuration.build(ENV) }
11
+ config = PgExport::Configuration.build(ENV)
12
+
13
+ formatters = {
14
+ plain: ->(_, _, _, message) { "#{message}\n" },
15
+ muted: ->(*) {},
16
+ timestamped: lambda do |severity, datetime, progname, message|
17
+ "#{datetime} #{Process.pid} TID-#{Thread.current.object_id.to_s(36)}#{progname} #{severity}: #{message}\n"
18
+ end
19
+ }
20
+
21
+ register(:logger, memoize: true) do
22
+ Logger.new($stdout, formatter: formatters.fetch(config.logger_format))
23
+ end
24
+
25
+ register(:config, memoize: true) { config }
10
26
  end
11
27
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ PgExport::Container.boot(:ftp) do
4
+ init do
5
+ require 'pg_export/lib/pg_export/factories/ftp_gateway_factory'
6
+ end
7
+
8
+ start do
9
+ register('factories.gateway_factory') { ::PgExport::Factories::FtpGatewayFactory.new }
10
+ end
11
+ end
@@ -6,27 +6,11 @@ PgExport::Container.boot(:interactive) do
6
6
  end
7
7
 
8
8
  start do
9
- use :main
10
-
11
- # type = 'plain'
12
- type = 'interactive'
13
-
14
- transaction = PgExport::Transactions::ImportDumpInteractively.new(ui_input: target["ui.#{type}.input"])
15
-
16
- unless target[:config].logger_muted?
17
- use :logger
18
-
19
- %i[
20
- open_ftp_connection
21
- fetch_dumps_from_ftp
22
- download_dump_from_ftp
23
- decrypt_dump
24
- restore
25
- ].each do |step|
26
- transaction.subscribe(step => target["listeners.#{type}.#{step}"])
27
- end
9
+ transaction = PgExport::Transactions::ImportDumpInteractively.new
10
+ transaction.steps.each do |step|
11
+ transaction.subscribe(step.name => target["listeners.interactive.#{step.name}"])
28
12
  end
29
13
 
30
- register('transactions.import_dump_interactively', memoize: true) { transaction }
14
+ register('transaction', memoize: true) { transaction }
31
15
  end
32
16
  end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ PgExport::Container.boot(:operations) do
4
+ init do
5
+ require 'pg_export/lib/pg_export/operations/encrypt_dump'
6
+ require 'pg_export/lib/pg_export/operations/decrypt_dump'
7
+ require 'pg_export/lib/pg_export/operations/remove_old_dumps'
8
+ require 'pg_export/lib/pg_export/operations/open_connection'
9
+ end
10
+
11
+ start do
12
+ register('operations.encrypt_dump') { ::PgExport::Operations::EncryptDump.new }
13
+ register('operations.decrypt_dump') { ::PgExport::Operations::DecryptDump.new }
14
+ register('operations.remove_old_dumps') { ::PgExport::Operations::RemoveOldDumps.new }
15
+ register('operations.open_connection') { ::PgExport::Operations::OpenConnection.new }
16
+ end
17
+ end
@@ -6,28 +6,11 @@ PgExport::Container.boot(:plain) do
6
6
  end
7
7
 
8
8
  start do
9
- use :main
10
-
11
9
  transaction = PgExport::Transactions::ExportDump.new
12
-
13
- unless target[:config].logger_muted?
14
- use :logger
15
-
16
- type = 'plain'
17
- # type = 'interactive'
18
-
19
- %i[
20
- build_dump
21
- encrypt_dump
22
- open_ftp_connection
23
- upload_dump_to_ftp
24
- remove_old_dumps_from_ftp
25
- close_ftp_connection
26
- ].each do |step|
27
- transaction.subscribe(step => target["listeners.#{type}.#{step}"])
28
- end
10
+ transaction.steps.each do |step|
11
+ transaction.subscribe(step.name => target["listeners.plain.#{step.name}"])
29
12
  end
30
13
 
31
- register('transactions.export_dump', memoize: true) { transaction }
14
+ register('transaction', memoize: true) { transaction }
32
15
  end
33
16
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ PgExport::Container.boot(:ssh) do
4
+ init do
5
+ require 'pg_export/lib/pg_export/factories/ssh_gateway_factory'
6
+ end
7
+
8
+ start do
9
+ register('factories.gateway_factory') { ::PgExport::Factories::SshGatewayFactory.new }
10
+ end
11
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class PgExport
4
- VERSION = '0.7.7'
4
+ VERSION = '1.0.0.rc5'
5
5
  end
data/pg_export.gemspec CHANGED
@@ -10,29 +10,33 @@ Gem::Specification.new do |spec|
10
10
  spec.authors = ['Krzysztof Maicher']
11
11
  spec.email = ['krzysztof.maicher@gmail.com']
12
12
 
13
- spec.summary = 'CLI for creating and exporting PostgreSQL dumps to FTP.'
14
- spec.description = "CLI for creating and exporting PostgreSQL dumps to FTP.\
13
+ spec.summary = 'CLI for exporting/importing PostgreSQL dumps via FTP/SSH.'
14
+ spec.description = "CLI for exporting/importing PostgreSQL dumps via FTP/SSH.\
15
15
  Can be used for backups or synchronizing databases between production and development environments."
16
16
  spec.homepage = 'https://github.com/maicher/pg_export'
17
17
  spec.license = 'MIT'
18
18
 
19
- spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
19
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^spec/}) }
20
20
  spec.executables = ['pg_export']
21
21
  spec.require_paths = ['lib']
22
22
  spec.required_ruby_version = '>= 2.3.0'
23
23
 
24
+ spec.add_dependency 'bcrypt_pbkdf'
24
25
  spec.add_dependency 'dry-initializer', '~> 3.0'
25
- spec.add_dependency 'dry-types', '~> 1.0'
26
26
  spec.add_dependency 'dry-struct', '~> 1.0'
27
27
  spec.add_dependency 'dry-system', '~> 0.18'
28
28
  spec.add_dependency 'dry-transaction', '~> 0.13'
29
+ spec.add_dependency 'dry-types', '~> 1.0'
30
+ spec.add_dependency 'ed25519'
31
+ spec.add_dependency 'net-scp'
32
+ spec.add_dependency 'net-ssh'
29
33
  spec.add_dependency 'tty-prompt'
30
34
  spec.add_dependency 'tty-spinner'
31
35
 
32
36
  spec.add_development_dependency 'bundler', '~> 2.1'
33
37
  spec.add_development_dependency 'pg', '~> 0.21'
34
38
  spec.add_development_dependency 'pry'
35
- spec.add_development_dependency 'rake', '~> 10.0'
39
+ spec.add_development_dependency 'rake', '>= 12.3.3'
36
40
  spec.add_development_dependency 'rspec', '~> 3.4'
37
41
  spec.add_development_dependency 'rubocop', '~> 0.59.2'
38
42
  end