pg_export 1.0.0.rc4 → 1.0.0.rc8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +42 -6
  3. data/CHANGELOG.md +10 -5
  4. data/README.md +63 -32
  5. data/bin/pg_export +15 -134
  6. data/lib/pg_export/{lib/pg_export/adapters/bash_adapter.rb → adapters/shell_adapter.rb} +1 -1
  7. data/lib/pg_export/commands_factory.rb +158 -0
  8. data/lib/pg_export/configuration.rb +74 -31
  9. data/lib/pg_export/configuration_parser.rb +126 -0
  10. data/lib/pg_export/entities/dump.rb +57 -0
  11. data/lib/pg_export/{lib/pg_export/factories → factories}/cipher_factory.rb +8 -4
  12. data/lib/pg_export/{lib/pg_export/factories → factories}/dump_factory.rb +1 -2
  13. data/lib/pg_export/{lib/pg_export/factories → factories}/ftp_gateway_factory.rb +8 -5
  14. data/lib/pg_export/{lib/pg_export/repositories/gateway_dump_file_repository.rb → factories/gateway_dump_file_factory.rb} +4 -5
  15. data/lib/pg_export/{lib/pg_export/factories → factories}/ssh_gateway_factory.rb +8 -5
  16. data/lib/pg_export/{lib/pg_export/gateways → gateways}/ftp.rb +1 -3
  17. data/lib/pg_export/{lib/pg_export/gateways → gateways}/ssh.rb +2 -6
  18. data/lib/pg_export/{lib/pg_export/listeners → listeners}/interactive/build_dump.rb +1 -1
  19. data/lib/pg_export/{lib/pg_export/listeners → listeners}/interactive/close_connection.rb +1 -1
  20. data/lib/pg_export/{lib/pg_export/listeners → listeners}/interactive/decrypt_dump.rb +0 -0
  21. data/lib/pg_export/{lib/pg_export/listeners → listeners}/interactive/download_dump.rb +0 -0
  22. data/lib/pg_export/{lib/pg_export/listeners → listeners}/interactive/encrypt_dump.rb +0 -0
  23. data/lib/pg_export/{lib/pg_export/listeners → listeners}/interactive/fetch_dumps.rb +0 -0
  24. data/lib/pg_export/{lib/pg_export/listeners → listeners}/interactive/open_connection.rb +0 -0
  25. data/lib/pg_export/{lib/pg_export/listeners → listeners}/interactive/remove_old_dumps.rb +1 -1
  26. data/lib/pg_export/{lib/pg_export/listeners → listeners}/interactive/restore.rb +1 -1
  27. data/lib/pg_export/listeners/interactive/select_database.rb +12 -0
  28. data/lib/pg_export/listeners/interactive/select_dump.rb +12 -0
  29. data/lib/pg_export/{lib/pg_export/listeners → listeners}/interactive/upload_dump.rb +1 -1
  30. data/lib/pg_export/{lib/pg_export/listeners → listeners}/interactive_listener.rb +4 -3
  31. data/lib/pg_export/{lib/pg_export/listeners → listeners}/plain/build_dump.rb +0 -0
  32. data/lib/pg_export/{lib/pg_export/listeners → listeners}/plain/close_connection.rb +0 -0
  33. data/lib/pg_export/{lib/pg_export/listeners → listeners}/plain/decrypt_dump.rb +0 -0
  34. data/lib/pg_export/{lib/pg_export/listeners → listeners}/plain/download_dump.rb +0 -0
  35. data/lib/pg_export/{lib/pg_export/listeners → listeners}/plain/encrypt_dump.rb +0 -0
  36. data/lib/pg_export/{lib/pg_export/listeners → listeners}/plain/fetch_dumps.rb +0 -0
  37. data/lib/pg_export/{lib/pg_export/listeners → listeners}/plain/open_connection.rb +0 -0
  38. data/lib/pg_export/listeners/plain/prepare_params.rb +15 -0
  39. data/lib/pg_export/{lib/pg_export/listeners → listeners}/plain/remove_old_dumps.rb +0 -0
  40. data/lib/pg_export/{lib/pg_export/listeners → listeners}/plain/restore.rb +0 -0
  41. data/lib/pg_export/{lib/pg_export/listeners → listeners}/plain/upload_dump.rb +0 -0
  42. data/lib/pg_export/{lib/pg_export/listeners → listeners}/plain_listener.rb +11 -5
  43. data/lib/pg_export/operations/decrypt_dump.rb +30 -0
  44. data/lib/pg_export/operations/encrypt_dump.rb +27 -0
  45. data/lib/pg_export/operations/open_connection.rb +28 -0
  46. data/lib/pg_export/operations/remove_old_dumps.rb +34 -0
  47. data/lib/pg_export/{lib/pg_export/repositories → repositories}/gateway_dump_repository.rb +4 -9
  48. data/lib/pg_export/transactions/evaluator.rb +59 -0
  49. data/lib/pg_export/transactions/export_dump.rb +62 -0
  50. data/lib/pg_export/transactions/import_dump_interactively.rb +78 -0
  51. data/lib/pg_export/{lib/pg_export/ui → ui}/interactive/input.rb +0 -0
  52. data/lib/pg_export/{lib/pg_export/ui → ui}/plain/input.rb +0 -0
  53. data/lib/pg_export/{lib/pg_export/value_objects → value_objects}/dump_file.rb +2 -2
  54. data/lib/pg_export/value_objects/result.rb +49 -0
  55. data/lib/pg_export/version.rb +1 -1
  56. data/lib/pg_export.rb +14 -11
  57. data/pg_export.gemspec +2 -9
  58. metadata +57 -129
  59. data/lib/pg_export/container.rb +0 -23
  60. data/lib/pg_export/import.rb +0 -7
  61. data/lib/pg_export/lib/pg_export/entities/dump.rb +0 -45
  62. data/lib/pg_export/lib/pg_export/operations/decrypt_dump.rb +0 -20
  63. data/lib/pg_export/lib/pg_export/operations/encrypt_dump.rb +0 -18
  64. data/lib/pg_export/lib/pg_export/operations/open_connection.rb +0 -19
  65. data/lib/pg_export/lib/pg_export/operations/remove_old_dumps.rb +0 -26
  66. data/lib/pg_export/lib/pg_export/transactions/export_dump.rb +0 -56
  67. data/lib/pg_export/lib/pg_export/transactions/import_dump_interactively.rb +0 -67
  68. data/lib/pg_export/lib/pg_export/types.rb +0 -14
  69. data/lib/pg_export/system/boot/config.rb +0 -27
  70. data/lib/pg_export/system/boot/ftp.rb +0 -11
  71. data/lib/pg_export/system/boot/interactive.rb +0 -26
  72. data/lib/pg_export/system/boot/operations.rb +0 -17
  73. data/lib/pg_export/system/boot/plain.rb +0 -27
  74. data/lib/pg_export/system/boot/ssh.rb +0 -11
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pg_export'
4
+ require 'pg_export/value_objects/result'
5
+
6
+ class PgExport
7
+ module Operations
8
+ class DecryptDump
9
+ def initialize(cipher_factory:)
10
+ @cipher_factory = cipher_factory
11
+ end
12
+
13
+ def name
14
+ :decrypt_dump
15
+ end
16
+
17
+ def call(dump:)
18
+ dump.decrypt(cipher_factory: cipher_factory)
19
+
20
+ ValueObjects::Success.new(dump: dump)
21
+ rescue OpenSSL::Cipher::CipherError => e
22
+ ValueObjects::Failure.new(message: "Problem decrypting dump file: #{e}. Try again.")
23
+ end
24
+
25
+ private
26
+
27
+ attr_reader :cipher_factory
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pg_export/value_objects/result'
4
+
5
+ class PgExport
6
+ module Operations
7
+ class EncryptDump
8
+ def initialize(cipher_factory:)
9
+ @cipher_factory = cipher_factory
10
+ end
11
+
12
+ def name
13
+ :encrypt_dump
14
+ end
15
+
16
+ def call(dump:)
17
+ dump.encrypt(cipher_factory: cipher_factory)
18
+
19
+ ValueObjects::Success.new(dump: dump)
20
+ end
21
+
22
+ private
23
+
24
+ attr_reader :cipher_factory
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pg_export/value_objects/result'
4
+
5
+ class PgExport
6
+ module Operations
7
+ class OpenConnection
8
+ def initialize(gateway_factory:)
9
+ @gateway_factory = gateway_factory
10
+ end
11
+
12
+ def name
13
+ :open_connection
14
+ end
15
+
16
+ def call(inputs)
17
+ gateway = gateway_factory.gateway
18
+ gateway.open
19
+
20
+ ValueObjects::Success.new(inputs.merge(gateway: gateway))
21
+ end
22
+
23
+ private
24
+
25
+ attr_reader :gateway_factory
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pg_export/value_objects/result'
4
+
5
+ class PgExport
6
+ module Operations
7
+ class RemoveOldDumps
8
+ def initialize(gateway_dump_repository:, keep:)
9
+ @gateway_dump_repository, @keep = gateway_dump_repository, keep
10
+ end
11
+
12
+ def name
13
+ :remove_old_dumps
14
+ end
15
+
16
+ def call(dump:, gateway:)
17
+ dumps = gateway_dump_repository.by_database_name(
18
+ database_name: dump.database,
19
+ gateway: gateway,
20
+ offset: keep
21
+ )
22
+ dumps.each do |d|
23
+ gateway.delete(d.name)
24
+ end
25
+
26
+ ValueObjects::Success.new(removed_dumps: dumps, gateway: gateway)
27
+ end
28
+
29
+ private
30
+
31
+ attr_reader :gateway_dump_repository, :keep
32
+ end
33
+ end
34
+ end
@@ -1,20 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
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'
4
+ require 'pg_export/entities/dump'
5
+ require 'pg_export/value_objects/dump_file'
7
6
 
8
7
  class PgExport
9
8
  module Repositories
10
9
  class GatewayDumpRepository
11
10
  def all(database_name:, gateway:)
12
11
  gateway.list(database_name).map do |item|
13
- begin
14
- dump(item[:name], database_name, item[:size])
15
- rescue Dry::Types::ConstraintError
16
- nil
17
- end
12
+ dump(item[:name], database_name, item[:size])
18
13
  end.compact
19
14
  end
20
15
 
@@ -22,7 +17,7 @@ class PgExport
22
17
  gateway.list(database_name).drop(offset).map do |item|
23
18
  begin
24
19
  dump(item[:name], database_name, item[:size])
25
- rescue Dry::Types::ConstraintError
20
+ rescue ArgumentError
26
21
  nil
27
22
  end
28
23
  end.compact
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ class PgExport
4
+ module Transactions
5
+ class Evaluator
6
+ def initialize(listeners)
7
+ @operations = []
8
+ @listeners = listeners
9
+ end
10
+
11
+ def <<(operation)
12
+ operations << operation
13
+ end
14
+
15
+ def call(input)
16
+ result = ValueObjects::Success.new(input)
17
+
18
+ operations.each do |operation|
19
+ result = result.bind do
20
+ call_operation(operation, result)
21
+ end
22
+ end
23
+
24
+ result
25
+ end
26
+
27
+ private
28
+
29
+ attr_reader :operations, :listeners
30
+
31
+ def call_operation(operation, input)
32
+ listener = listeners[operation.name]
33
+
34
+ before_call(listener, input)
35
+ result = operation.call(**input.value)
36
+ after_call(listener, result)
37
+ result
38
+ end
39
+
40
+ def before_call(listener, input)
41
+ return if listener.nil?
42
+
43
+ listener.on_step(value: input.value)
44
+ end
45
+
46
+ def after_call(listener, result)
47
+ return if listener.nil?
48
+
49
+ result.on_success do
50
+ listener.on_step_succeeded(value: result.value)
51
+ end
52
+
53
+ result.on_failure do
54
+ listener.on_step_failed(value: result.value)
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pg_export/transactions/evaluator'
4
+ require 'pg_export/value_objects/dump_file'
5
+ require 'pg_export/adapters/shell_adapter'
6
+ require 'pg_export/value_objects/result'
7
+
8
+ class PgExport
9
+ module Transactions
10
+ class ExportDump
11
+ def initialize(dump_factory:, shell_adapter:, encrypt_dump:, open_connection:, remove_old_dumps:, listeners:)
12
+ @dump_factory = dump_factory
13
+ @shell_adapter = shell_adapter
14
+
15
+ @evaluator = Evaluator.new(listeners)
16
+ @evaluator << method(:prepare_params)
17
+ @evaluator << method(:build_dump)
18
+ @evaluator << encrypt_dump
19
+ @evaluator << open_connection
20
+ @evaluator << method(:upload_dump)
21
+ @evaluator << remove_old_dumps
22
+ @evaluator << method(:close_connection)
23
+ end
24
+
25
+ def call(input)
26
+ evaluator.call(input)
27
+ end
28
+
29
+ private
30
+
31
+ attr_reader :evaluator, :dump_factory, :shell_adapter
32
+
33
+ def prepare_params(database_name:)
34
+ database_name = database_name.to_s
35
+
36
+ return ValueObjects::Failure.new(message: 'Invalid database name') if database_name.empty?
37
+
38
+ ValueObjects::Success.new(database_name: database_name)
39
+ end
40
+
41
+ def build_dump(database_name:)
42
+ dump = dump_factory.plain(
43
+ database: database_name,
44
+ file: shell_adapter.pg_dump(ValueObjects::DumpFile.new, database_name)
45
+ )
46
+ ValueObjects::Success.new(dump: dump)
47
+ rescue Adapters::ShellAdapter::PgDumpError => e
48
+ ValueObjects::Failure.new(message: 'Unable to dump database: ' + e.to_s)
49
+ end
50
+
51
+ def upload_dump(dump:, gateway:)
52
+ gateway.persist(dump.file, dump.name)
53
+ ValueObjects::Success.new(dump: dump, gateway: gateway)
54
+ end
55
+
56
+ def close_connection(removed_dumps:, gateway:)
57
+ gateway.close
58
+ ValueObjects::Success.new
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pg_export/transactions/evaluator'
4
+ require 'pg_export/adapters/shell_adapter'
5
+ require 'pg_export/value_objects/result'
6
+
7
+ class PgExport
8
+ module Transactions
9
+ class ImportDumpInteractively
10
+ def initialize(
11
+ input:,
12
+ shell_adapter:,
13
+ gateway_dump_repository:,
14
+ gateway_dump_file_factory:,
15
+ open_connection:,
16
+ decrypt_dump:,
17
+ listeners:
18
+ )
19
+ @input = input
20
+ @shell_adapter = shell_adapter
21
+ @gateway_dump_repository = gateway_dump_repository
22
+ @gateway_dump_file_factory = gateway_dump_file_factory
23
+
24
+ @evaluator = Evaluator.new(listeners)
25
+ @evaluator << open_connection
26
+ @evaluator << method(:fetch_dumps)
27
+ @evaluator << method(:select_dump)
28
+ @evaluator << method(:download_dump)
29
+ @evaluator << method(:close_connection)
30
+ @evaluator << decrypt_dump
31
+ @evaluator << method(:select_database)
32
+ @evaluator << method(:restore)
33
+ end
34
+
35
+ def call(input)
36
+ evaluator.call(input)
37
+ end
38
+
39
+ private
40
+
41
+ attr_reader :evaluator, :input, :shell_adapter, :gateway_dump_repository, :gateway_dump_file_factory
42
+
43
+ def fetch_dumps(database_name:, gateway:)
44
+ dumps = gateway_dump_repository.all(database_name: database_name, gateway: gateway)
45
+ return ValueObjects::Failure.new(message: 'No dumps') if dumps.none?
46
+
47
+ ValueObjects::Success.new(gateway: gateway, dumps: dumps)
48
+ end
49
+
50
+ def select_dump(dumps:, gateway:)
51
+ dump = input.select_dump(dumps)
52
+ ValueObjects::Success.new(dump: dump, gateway: gateway)
53
+ end
54
+
55
+ def download_dump(dump:, gateway:)
56
+ dump.file = gateway_dump_file_factory.by_name(name: dump.name, gateway: gateway)
57
+ ValueObjects::Success.new(dump: dump, gateway: gateway)
58
+ end
59
+
60
+ def close_connection(dump:, gateway:)
61
+ Thread.new { gateway.close }
62
+ ValueObjects::Success.new(dump: dump)
63
+ end
64
+
65
+ def select_database(dump:)
66
+ name = input.enter_database_name(dump.database)
67
+ ValueObjects::Success.new(dump: dump, database: name)
68
+ end
69
+
70
+ def restore(dump:, database:)
71
+ shell_adapter.pg_restore(dump.file, database)
72
+ ValueObjects::Success.new(nil)
73
+ rescue Adapters::ShellAdapter::PgRestoreError => e
74
+ ValueObjects::Failure.new(message: e.to_s)
75
+ end
76
+ end
77
+ end
78
+ end
@@ -54,9 +54,9 @@ class PgExport
54
54
 
55
55
  private
56
56
 
57
- CHUNK_SIZE = (2**16).freeze
57
+ CHUNK_SIZE = (2**16)
58
58
  MAPPING = {
59
- 'B' => 1024,
59
+ 'B' => 1024,
60
60
  'kB' => 1024 * 1024,
61
61
  'MB' => 1024 * 1024 * 1024,
62
62
  'GB' => 1024 * 1024 * 1024 * 1024,
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ class PgExport
4
+ module ValueObjects
5
+ class Result
6
+ attr_reader :value
7
+
8
+ def initialize(value = nil)
9
+ @value = value
10
+ end
11
+ end
12
+
13
+ class Success < Result
14
+ def success
15
+ value
16
+ end
17
+
18
+ def bind
19
+ yield
20
+ end
21
+
22
+ def on_success
23
+ yield value
24
+
25
+ self
26
+ end
27
+
28
+ def on_failure
29
+ self
30
+ end
31
+ end
32
+
33
+ class Failure < Result
34
+ def bind
35
+ self
36
+ end
37
+
38
+ def on_success
39
+ self
40
+ end
41
+
42
+ def on_failure
43
+ yield value
44
+
45
+ self
46
+ end
47
+ end
48
+ end
49
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class PgExport
4
- VERSION = '1.0.0.rc4'
4
+ VERSION = '1.0.0.rc8'
5
5
  end
data/lib/pg_export.rb CHANGED
@@ -1,23 +1,26 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'pg_export/container'
4
- require 'pg_export/import'
3
+ require 'pg_export/version'
4
+ require 'pg_export/configuration'
5
+ require 'pg_export/configuration_parser'
6
+ require 'pg_export/commands_factory'
5
7
 
6
8
  class PgExport
7
- class InitializationError < StandardError; end
9
+ def initialize(config)
10
+ raise ArgumentError, 'config is not a PgExport::Configuration' unless config.is_a?(PgExport::Configuration)
8
11
 
9
- include Import['transaction']
10
-
11
- def self.boot
12
- PgExport::Container.start(:main)
13
- new
12
+ @command_name = config.command
13
+ @database_name = config.database
14
+ @commands_factory = PgExport::CommandsFactory.new(config: config)
14
15
  end
15
16
 
16
- def call(database_name, &block)
17
- transaction.call(database_name: database_name, &block)
17
+ def call
18
+ commands_factory
19
+ .public_send(command_name)
20
+ .call(database_name: database_name)
18
21
  end
19
22
 
20
23
  private
21
24
 
22
- attr_reader :transaction
25
+ attr_reader :command_name, :database_name, :commands_factory
23
26
  end
data/pg_export.gemspec CHANGED
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- lib = File.expand_path('lib', __dir__)
4
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
- require 'pg_export/version'
3
+ require_relative 'lib/pg_export/version'
6
4
 
7
5
  Gem::Specification.new do |spec|
8
6
  spec.name = 'pg_export'
@@ -22,11 +20,6 @@ Gem::Specification.new do |spec|
22
20
  spec.required_ruby_version = '>= 2.3.0'
23
21
 
24
22
  spec.add_dependency 'bcrypt_pbkdf'
25
- spec.add_dependency 'dry-initializer', '~> 3.0'
26
- spec.add_dependency 'dry-struct', '~> 1.0'
27
- spec.add_dependency 'dry-system', '~> 0.18'
28
- spec.add_dependency 'dry-transaction', '~> 0.13'
29
- spec.add_dependency 'dry-types', '~> 1.0'
30
23
  spec.add_dependency 'ed25519'
31
24
  spec.add_dependency 'net-scp'
32
25
  spec.add_dependency 'net-ssh'
@@ -38,5 +31,5 @@ Gem::Specification.new do |spec|
38
31
  spec.add_development_dependency 'pry'
39
32
  spec.add_development_dependency 'rake', '>= 12.3.3'
40
33
  spec.add_development_dependency 'rspec', '~> 3.4'
41
- spec.add_development_dependency 'rubocop', '~> 0.59.2'
34
+ spec.add_development_dependency 'rubocop', '= 0.81'
42
35
  end