pg_export 0.7.7 → 1.0.0.rc5

Sign up to get free protection for your applications and to get access to all the features.
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