pg_export 0.7.3 → 1.0.0.rc1

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 (48) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +6 -3
  4. data/CHANGELOG.md +17 -0
  5. data/README.md +13 -10
  6. data/bin/pg_export +20 -7
  7. data/lib/pg_export/configuration.rb +12 -8
  8. data/lib/pg_export/container.rb +17 -8
  9. data/lib/pg_export/import.rb +1 -1
  10. data/lib/pg_export/lib/pg_export/factories/ftp_gateway_factory.rb +22 -0
  11. data/lib/pg_export/lib/pg_export/factories/ssh_gateway_factory.rb +22 -0
  12. data/lib/pg_export/lib/pg_export/{adapters/ftp_adapter.rb → gateways/ftp.rb} +9 -6
  13. data/lib/pg_export/lib/pg_export/gateways/ssh.rb +74 -0
  14. data/lib/pg_export/lib/pg_export/listeners/interactive/build_dump.rb +4 -4
  15. data/lib/pg_export/lib/pg_export/listeners/interactive/{close_ftp_connection.rb → close_connection.rb} +1 -1
  16. data/lib/pg_export/lib/pg_export/listeners/interactive/decrypt_dump.rb +2 -2
  17. data/lib/pg_export/lib/pg_export/listeners/interactive/download_dump_from_ftp.rb +2 -2
  18. data/lib/pg_export/lib/pg_export/listeners/interactive/encrypt_dump.rb +2 -2
  19. data/lib/pg_export/lib/pg_export/listeners/interactive/{open_ftp_connection.rb → open_connection.rb} +1 -1
  20. data/lib/pg_export/lib/pg_export/listeners/interactive/remove_old_dumps_from_ftp.rb +5 -5
  21. data/lib/pg_export/lib/pg_export/listeners/interactive/restore.rb +2 -2
  22. data/lib/pg_export/lib/pg_export/listeners/interactive/upload_dump_to_ftp.rb +2 -2
  23. data/lib/pg_export/lib/pg_export/listeners/interactive_listener.rb +2 -2
  24. data/lib/pg_export/lib/pg_export/listeners/plain/build_dump.rb +2 -2
  25. data/lib/pg_export/lib/pg_export/listeners/plain/{close_ftp_connection.rb → close_connection.rb} +2 -2
  26. data/lib/pg_export/lib/pg_export/listeners/plain/decrypt_dump.rb +2 -2
  27. data/lib/pg_export/lib/pg_export/listeners/plain/download_dump_from_ftp.rb +2 -2
  28. data/lib/pg_export/lib/pg_export/listeners/plain/encrypt_dump.rb +2 -2
  29. data/lib/pg_export/lib/pg_export/listeners/plain/fetch_dumps_from_ftp.rb +2 -2
  30. data/lib/pg_export/lib/pg_export/listeners/plain/open_connection.rb +15 -0
  31. data/lib/pg_export/lib/pg_export/listeners/plain/remove_old_dumps_from_ftp.rb +3 -3
  32. data/lib/pg_export/lib/pg_export/listeners/plain/restore.rb +1 -1
  33. data/lib/pg_export/lib/pg_export/listeners/plain/upload_dump_to_ftp.rb +2 -2
  34. data/lib/pg_export/lib/pg_export/listeners/plain_listener.rb +2 -2
  35. data/lib/pg_export/lib/pg_export/operations/{open_ftp_connection.rb → open_connection.rb} +5 -5
  36. data/lib/pg_export/lib/pg_export/operations/remove_old_dumps_from_ftp.rb +6 -6
  37. data/lib/pg_export/lib/pg_export/repositories/{ftp_dump_file_repository.rb → gateway_dump_file_repository.rb} +3 -3
  38. data/lib/pg_export/lib/pg_export/repositories/{ftp_dump_repository.rb → gateway_dump_repository.rb} +7 -7
  39. data/lib/pg_export/lib/pg_export/transactions/export_dump.rb +8 -8
  40. data/lib/pg_export/lib/pg_export/transactions/import_dump_interactively.rb +14 -14
  41. data/lib/pg_export/lib/pg_export/types.rb +1 -1
  42. data/lib/pg_export/system/boot/interactive.rb +1 -1
  43. data/lib/pg_export/system/boot/plain.rb +2 -2
  44. data/lib/pg_export/version.rb +1 -1
  45. data/pg_export.gemspec +10 -6
  46. metadata +84 -27
  47. data/lib/pg_export/lib/pg_export/factories/ftp_adapter_factory.rb +0 -22
  48. data/lib/pg_export/lib/pg_export/listeners/plain/open_ftp_connection.rb +0 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b37e313458127333a2dbe576aa319542438d996d10874cf545054b83a056dfc2
4
- data.tar.gz: 5b64bcdc82a31242b7dd0c1676771a8942f06ce5ca884bb66bcb664001001b17
3
+ metadata.gz: 3eb793296ca1e2e22519a8abf1644f88fd06daa02a672d392f318a19128c50cb
4
+ data.tar.gz: '085a37ec1e0b7cc96f811e73a0a3271086e1c12fba3e6a2da831c6f58a4f9fde'
5
5
  SHA512:
6
- metadata.gz: fcd767643cba4b7834600d7715fe76605f76f04606f9c01b4f938ff9a02e50399fa5629f931881ddc8afba117c44bb6466ec4f55aad6c900acb818347b2ab4a1
7
- data.tar.gz: 4ad8e9393779a16fcf40e38acb4074df20fe134e071842d13386899ef65af58d977900dc16bd699ea3c846d229b49bf7114fab253960c7a925b4d3b8811f8dfa
6
+ metadata.gz: a3b89d600dc035cca7cdc909b503ac1d62e7844531d5f8a35c8213339968074ccb21d49669a1623f3d616f0aa52c2ccfb1c6c0a54f864e602ffcbe32a43c0886
7
+ data.tar.gz: 9a93edd9855a3a20d5745491cedbcff104cd8aee180e1c10537c63c129c8ed96933f36d5120476b85812aece2bcaba507391910e282097b5a8555e210a0e209e
data/.gitignore CHANGED
@@ -7,3 +7,4 @@
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
+ .idea
data/.travis.yml CHANGED
@@ -1,9 +1,12 @@
1
- sudo: false
2
1
  language: ruby
3
2
  rvm:
4
- - 2.3.0
3
+ - 3.0.0
4
+ - 2.7.2
5
+ - 2.4.10
6
+ services:
7
+ - postgresql
5
8
  addons:
6
9
  code_climate:
7
10
  repo_token: db03e5968c5bcd68b12ca50f5d41ae07dd74fe80d4e1421d754e31c316e7477a
8
- before_install: gem install bundler -v 1.16.6
11
+ before_install: gem install bundler -v 2.2.3
9
12
  after_success: codeclimate-test-reporter
data/CHANGELOG.md CHANGED
@@ -1,3 +1,20 @@
1
+ ### 1.0.0 - 2021.03.20
2
+ - Make it compatible with Ruby 3.0
3
+ - Change configuration envs:
4
+ - BACKUP_FTP_HOST -> PG_EXPORT_GATEWAY_HOST
5
+ - BACKUP_FTP_USER -> PG_EXPORT_GATEWAY_USER
6
+ - BACKUP_FTP_PASSWORD -> PG_EXPORT_GATEWAY_PASSWORD
7
+ - DUMP_ENCRYPTION_KEY -> PG_EXPORT_ENCRYPTION_KEY
8
+ - Drop Ruby 2.3 support
9
+
10
+ ### 0.7.7 - 2020.09.07
11
+
12
+ - Upgrade dry-initializer
13
+
14
+ ### 0.7.6 - 2020.09.05
15
+
16
+ - Upgrade dry-types, dry-struct dry-system
17
+
1
18
  ### 0.7.0 - 2018.10.18
2
19
 
3
20
  - Change required ruby version from 2.2.0 to 2.3.0.
data/README.md CHANGED
@@ -26,7 +26,7 @@ Features:
26
26
 
27
27
  ## Dependencies
28
28
 
29
- * Ruby >= 2.3.0
29
+ * Ruby >= 2.4 (works with Ruby 3.0)
30
30
  * $ pg_dump
31
31
  * $ pg_restore
32
32
 
@@ -51,29 +51,32 @@ Or install it yourself as:
51
51
  $ pg_export -h
52
52
 
53
53
  Usage: pg_export [options]
54
+ -g, --gateway GATEWAY [Optional] ssh or ftp (default: ftp)
54
55
  -d, --database DATABASE [Required] Name of the database to export
55
56
  -k, --keep [KEEP] [Optional] Number of dump files to keep on FTP (default: 10)
56
57
  -t, --timestamped [Optional] Enables log messages with timestamps
57
58
  -m, --muted [Optional] Mutes log messages (overrides -t option)
58
59
  -i, --interactive [Optional] Interactive command line mode - for restoring dumps into databases
60
+ -v, --version Show version
59
61
  -h, --help Show this message
60
-
62
+
61
63
  Setting can be verified by running following commands:
62
64
  -c, --configuration Prints the configuration
63
- -f, --ftp Tries connecting to FTP to verify the connection
65
+ -w, --welcome Tries connecting to the gateway (FTP or SSH) to verify the connection
66
+
64
67
 
65
68
  ## How to start
66
69
 
67
70
  __Step 1.__ Prepare ENV variables.
68
71
 
69
72
  /* FTP storage for database dumps. */
70
- BACKUP_FTP_HOST=yourftp.example.com
71
- BACKUP_FTP_USER=user
72
- BACKUP_FTP_PASSWORD=password
73
+ PG_EXPORT_GATEWAY_HOST=yourftp.example.com
74
+ PG_EXPORT_GATEWAY_USER=user
75
+ PG_EXPORT_GATEWAY_PASSWORD=password
73
76
 
74
77
  /* Encryption key shoul have exactly 16 characters. */
75
78
  /* Dumps will be SSL(AES-128-CBC) encrypted using this key. */
76
- DUMP_ENCRYPTION_KEY=1234567890abcdef
79
+ PG_EXPORT_ENCRYPTION_KEY=1234567890abcdef
77
80
 
78
81
  /* Dumps to be kept on FTP */
79
82
  /* Optional, defaults to 10 */
@@ -84,12 +87,12 @@ Note, that variables cannot include `#` sign, [more info](http://serverfault.com
84
87
  __Step 2.__ Print the configuration to verify if env variables has been loaded properly.
85
88
 
86
89
  $ pg_export --configuration
87
- => {:dump_encryption_key=>"k4***", :ftp_host=>"yourftp.example.com", :ftp_user=>"your_ftp_user",
88
- :ftp_password=>"pass***", :logger_format=>"plain", :keep_dumps=>2}
90
+ => {:dump_encryption_key=>"k4***", :gateway_host=>"yourftp.example.com", :gateway_user=>"your_gateway_user",
91
+ :gateway_password=>"pass***", :logger_format=>"plain", :keep_dumps=>2}
89
92
 
90
93
  __Step 3.__ Try connecting to FTP to verify the connection.
91
94
 
92
- $ pg_export --ftp
95
+ $ pg_export --gateway ftp --welcome
93
96
  => 230 User your_ftp_user logged in
94
97
 
95
98
  __Step 4.__ Perform database export.
data/bin/pg_export CHANGED
@@ -4,15 +4,20 @@
4
4
  require 'optparse'
5
5
 
6
6
  require 'pg_export'
7
- require 'pg_export/container'
8
7
 
9
8
  ENV['KEEP_DUMPS'] = ENV['KEEP_DUMPS'] || '10'
9
+ ENV['GATEWAY'] = 'ftp'
10
+
10
11
  interactive = false
11
12
  database = nil
12
13
 
13
14
  option_parser = OptionParser.new do |opts|
14
15
  opts.banner = 'Usage: pg_export [options]'
15
16
 
17
+ opts.on('-g', '--gateway GATEWAY', String, '[Optional] ssh or ftp (default: ftp)') do |g|
18
+ ENV['GATEWAY'] = g
19
+ end
20
+
16
21
  opts.on('-d', '--database DATABASE', String, '[Required] Name of the database to export') do |d|
17
22
  database = d
18
23
  end
@@ -33,6 +38,11 @@ option_parser = OptionParser.new do |opts|
33
38
  interactive = true
34
39
  end
35
40
 
41
+ opts.on('-v', '--version', 'Show version') do
42
+ puts PgExport::VERSION
43
+ exit
44
+ end
45
+
36
46
  opts.on('-h', '--help', 'Show this message') do
37
47
  puts opts
38
48
  exit
@@ -41,16 +51,17 @@ option_parser = OptionParser.new do |opts|
41
51
  opts.separator "\nSetting can be verified by running following commands:"
42
52
 
43
53
  opts.on('-c', '--configuration', 'Prints the configuration') do
54
+ require 'pg_export/container'
44
55
  PgExport::Container.start(:config)
45
56
  puts PgExport::Container['config'].to_h
46
57
  exit
47
58
  end
48
59
 
49
- opts.on('-f', '--ftp', 'Tries connecting to FTP to verify the connection') do
50
- PgExport::Container.start(:ftp)
51
- ftp_adapter = PgExport::Container['factories.ftp_adapter_factory'].ftp_adapter
52
- ftp = ftp_adapter.open_ftp
53
- puts ftp.welcome
60
+ opts.on('-w', '--welcome', 'Tries connecting to the gateway (FTP or SSH) to verify the connection') do
61
+ require 'pg_export/container'
62
+ PgExport::Container.start(ENV['GATEWAY'].to_sym)
63
+ gateway = PgExport::Container['factories.gateway_factory'].gateway
64
+ puts gateway.welcome
54
65
  exit
55
66
  end
56
67
  end
@@ -63,6 +74,8 @@ rescue OptionParser::ParseError => e
63
74
  exit
64
75
  end
65
76
 
77
+ require 'pg_export/container'
78
+
66
79
  begin
67
80
  pg_export =
68
81
  if interactive
@@ -78,5 +91,5 @@ end
78
91
 
79
92
  pg_export.call(database) do |result|
80
93
  result.success { puts 'Success' }
81
- result.failure { |message:| warn message }
94
+ result.failure { |outcome| warn outcome[:message] }
82
95
  end
@@ -5,21 +5,21 @@ require 'dry-struct'
5
5
 
6
6
  class PgExport
7
7
  class Configuration < Dry::Struct
8
- include Dry::Types.module
8
+ include Dry::Types()
9
9
 
10
10
  attribute :dump_encryption_key, Strict::String.constrained(size: 16)
11
- attribute :ftp_host, Strict::String
12
- attribute :ftp_user, Strict::String
13
- attribute :ftp_password, Strict::String
11
+ attribute :gateway_host, Strict::String
12
+ attribute :gateway_user, Strict::String
13
+ attribute :gateway_password, Strict::String.optional
14
14
  attribute :logger_format, Coercible::String.enum('plain', 'timestamped', 'muted')
15
15
  attribute :keep_dumps, Coercible::Integer.constrained(gteq: 0)
16
16
 
17
17
  def self.build(env)
18
18
  new(
19
- dump_encryption_key: env['DUMP_ENCRYPTION_KEY'],
20
- ftp_host: env['BACKUP_FTP_HOST'],
21
- ftp_user: env['BACKUP_FTP_USER'],
22
- ftp_password: env['BACKUP_FTP_PASSWORD'],
19
+ dump_encryption_key: env['PG_EXPORT_ENCRYPTION_KEY'],
20
+ gateway_host: env['PG_EXPORT_GATEWAY_HOST'],
21
+ gateway_user: env['PG_EXPORT_GATEWAY_USER'],
22
+ gateway_password: env['PG_EXPORT_GATEWAY_PASSWORD'] == '' ? nil : env['PG_EXPORT_GATEWAY_PASSWORD'],
23
23
  logger_format: env['LOGGER_FORMAT'] || 'plain',
24
24
  keep_dumps: env['KEEP_DUMPS'] || 10
25
25
  )
@@ -27,6 +27,10 @@ class PgExport
27
27
  raise PgExport::InitializationError, e.message.gsub('[PgExport::Configuration.new] ', '')
28
28
  end
29
29
 
30
+ def gateway
31
+ ENV['GATEWAY'].to_sym
32
+ end
33
+
30
34
  def logger_muted?
31
35
  logger_format == 'muted'
32
36
  end
@@ -16,32 +16,41 @@ class PgExport
16
16
 
17
17
  boot(:ftp) do
18
18
  init do
19
- require 'pg_export/lib/pg_export/factories/ftp_adapter_factory'
19
+ require 'pg_export/lib/pg_export/factories/ftp_gateway_factory'
20
20
  end
21
21
 
22
22
  start do
23
23
  use :config
24
+ register('factories.gateway_factory') { ::PgExport::Factories::FtpGatewayFactory.new }
25
+ end
26
+ end
27
+
28
+ boot(:ssh) do
29
+ init do
30
+ require 'pg_export/lib/pg_export/factories/ssh_gateway_factory'
31
+ end
24
32
 
25
- register('factories.ftp_adapter_factory') do
26
- ::PgExport::Factories::FtpAdapterFactory.new
27
- end
33
+ start do
34
+ use :config
35
+ register('factories.gateway_factory') { ::PgExport::Factories::SshGatewayFactory.new }
28
36
  end
29
37
  end
30
38
 
31
- boot(:main) do
39
+ boot(:main) do |system|
32
40
  init do
33
41
  require 'pg_export/lib/pg_export/operations/encrypt_dump'
34
42
  require 'pg_export/lib/pg_export/operations/decrypt_dump'
35
43
  require 'pg_export/lib/pg_export/operations/remove_old_dumps_from_ftp'
36
- require 'pg_export/lib/pg_export/operations/open_ftp_connection'
44
+ require 'pg_export/lib/pg_export/operations/open_connection'
37
45
  end
38
46
 
39
47
  start do
40
- use :ftp
48
+ use(system[:config].gateway)
49
+
41
50
  register('operations.encrypt_dump') { ::PgExport::Operations::EncryptDump.new }
42
51
  register('operations.decrypt_dump') { ::PgExport::Operations::DecryptDump.new }
43
52
  register('operations.remove_old_dumps_from_ftp') { ::PgExport::Operations::RemoveOldDumpsFromFtp.new }
44
- register('operations.open_ftp_connection') { ::PgExport::Operations::OpenFtpConnection.new }
53
+ register('operations.open_connection') { ::PgExport::Operations::OpenConnection.new }
45
54
  end
46
55
  end
47
56
  end
@@ -3,5 +3,5 @@
3
3
  require_relative 'container'
4
4
 
5
5
  class PgExport
6
- Import = PgExport::Container.injector.hash
6
+ Import = PgExport::Container.injector
7
7
  end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ # auto_register: false
4
+
5
+ require 'pg_export/lib/pg_export/gateways/ftp'
6
+ require 'pg_export/import'
7
+
8
+ class PgExport
9
+ module Factories
10
+ class FtpGatewayFactory
11
+ include Import['config']
12
+
13
+ def gateway
14
+ ::PgExport::Gateways::Ftp.new(
15
+ host: config.gateway_host,
16
+ user: config.gateway_user,
17
+ password: config.gateway_password
18
+ )
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ # auto_register: false
4
+
5
+ require 'pg_export/lib/pg_export/gateways/ssh'
6
+ require 'pg_export/import'
7
+
8
+ class PgExport
9
+ module Factories
10
+ class SshGatewayFactory
11
+ include Import['config']
12
+
13
+ def gateway
14
+ ::PgExport::Gateways::Ssh.new(
15
+ host: config.gateway_host,
16
+ user: config.gateway_user,
17
+ password: config.gateway_password
18
+ )
19
+ end
20
+ end
21
+ end
22
+ end
@@ -5,22 +5,25 @@
5
5
  require 'net/ftp'
6
6
 
7
7
  class PgExport
8
- module Adapters
9
- class FtpAdapter
8
+ module Gateways
9
+ class Ftp
10
10
  CHUNK_SIZE = (2**16).freeze
11
11
 
12
12
  def initialize(host:, user:, password:)
13
13
  @host, @user, @password, @logger = host, user, password
14
- ObjectSpace.define_finalizer(self, proc { ftp.close if @ftp })
15
14
  end
16
15
 
17
- def open_ftp
16
+ def open
18
17
  @ftp = Net::FTP.new(host, user, password)
19
18
  @ftp.passive = true
20
19
  @ftp
21
20
  end
22
21
 
23
- def close_ftp
22
+ def welcome
23
+ open.welcome
24
+ end
25
+
26
+ def close
24
27
  @ftp&.close
25
28
  end
26
29
 
@@ -49,7 +52,7 @@ class PgExport
49
52
  end
50
53
 
51
54
  def ftp
52
- @ftp ||= open_ftp
55
+ @ftp ||= open
53
56
  end
54
57
 
55
58
  private
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ # auto_register: false
4
+
5
+ require 'net/ssh'
6
+ require 'net/scp'
7
+
8
+ class PgExport
9
+ module Gateways
10
+ class Ssh
11
+ CHUNK_SIZE = (2**16).freeze
12
+
13
+ def initialize(host:, user:, password:)
14
+ @host, @user, @password, @logger = host, user, password
15
+ end
16
+
17
+ def open
18
+ if password.nil?
19
+ @ssh = Net::SSH.start(host, user)
20
+ else
21
+ @ssh = Net::SSH.start(host, user, password)
22
+ end
23
+ end
24
+
25
+ def welcome
26
+ open.exec!('hostname')
27
+ end
28
+
29
+ def close
30
+ @ssh&.close
31
+ end
32
+
33
+ def list(regex_string)
34
+ ssh
35
+ .exec!("ls -l | grep #{regex_string.gsub('*', '')}")
36
+ .split("\n")
37
+ .map { |row| extract_meaningful_attributes(row) }
38
+ .sort_by { |item| item[:name] }
39
+ .reverse
40
+ end
41
+
42
+ def delete(name)
43
+ # @TODO
44
+ end
45
+
46
+ def persist(file, name)
47
+ ssh.scp.upload(file.path, name).wait
48
+ end
49
+
50
+ def get(file, name)
51
+ ssh.scp.download(name, file.path).wait
52
+ end
53
+
54
+ def to_s
55
+ host
56
+ end
57
+
58
+ def ssh
59
+ @ssh ||= open
60
+ end
61
+
62
+ private
63
+
64
+ attr_reader :host, :user, :password
65
+
66
+ def extract_meaningful_attributes(item)
67
+ MEANINGFUL_KEYS.zip(item.split(' ').values_at(8, 4)).to_h
68
+ end
69
+
70
+ MEANINGFUL_KEYS = %i[name size].freeze
71
+ private_constant :MEANINGFUL_KEYS
72
+ end
73
+ end
74
+ end