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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +6 -3
- data/CHANGELOG.md +17 -0
- data/README.md +13 -10
- data/bin/pg_export +20 -7
- data/lib/pg_export/configuration.rb +12 -8
- data/lib/pg_export/container.rb +17 -8
- data/lib/pg_export/import.rb +1 -1
- data/lib/pg_export/lib/pg_export/factories/ftp_gateway_factory.rb +22 -0
- data/lib/pg_export/lib/pg_export/factories/ssh_gateway_factory.rb +22 -0
- data/lib/pg_export/lib/pg_export/{adapters/ftp_adapter.rb → gateways/ftp.rb} +9 -6
- data/lib/pg_export/lib/pg_export/gateways/ssh.rb +74 -0
- data/lib/pg_export/lib/pg_export/listeners/interactive/build_dump.rb +4 -4
- data/lib/pg_export/lib/pg_export/listeners/interactive/{close_ftp_connection.rb → close_connection.rb} +1 -1
- data/lib/pg_export/lib/pg_export/listeners/interactive/decrypt_dump.rb +2 -2
- data/lib/pg_export/lib/pg_export/listeners/interactive/download_dump_from_ftp.rb +2 -2
- data/lib/pg_export/lib/pg_export/listeners/interactive/encrypt_dump.rb +2 -2
- data/lib/pg_export/lib/pg_export/listeners/interactive/{open_ftp_connection.rb → open_connection.rb} +1 -1
- data/lib/pg_export/lib/pg_export/listeners/interactive/remove_old_dumps_from_ftp.rb +5 -5
- data/lib/pg_export/lib/pg_export/listeners/interactive/restore.rb +2 -2
- data/lib/pg_export/lib/pg_export/listeners/interactive/upload_dump_to_ftp.rb +2 -2
- data/lib/pg_export/lib/pg_export/listeners/interactive_listener.rb +2 -2
- data/lib/pg_export/lib/pg_export/listeners/plain/build_dump.rb +2 -2
- data/lib/pg_export/lib/pg_export/listeners/plain/{close_ftp_connection.rb → close_connection.rb} +2 -2
- data/lib/pg_export/lib/pg_export/listeners/plain/decrypt_dump.rb +2 -2
- data/lib/pg_export/lib/pg_export/listeners/plain/download_dump_from_ftp.rb +2 -2
- data/lib/pg_export/lib/pg_export/listeners/plain/encrypt_dump.rb +2 -2
- data/lib/pg_export/lib/pg_export/listeners/plain/fetch_dumps_from_ftp.rb +2 -2
- data/lib/pg_export/lib/pg_export/listeners/plain/open_connection.rb +15 -0
- data/lib/pg_export/lib/pg_export/listeners/plain/remove_old_dumps_from_ftp.rb +3 -3
- data/lib/pg_export/lib/pg_export/listeners/plain/restore.rb +1 -1
- data/lib/pg_export/lib/pg_export/listeners/plain/upload_dump_to_ftp.rb +2 -2
- data/lib/pg_export/lib/pg_export/listeners/plain_listener.rb +2 -2
- data/lib/pg_export/lib/pg_export/operations/{open_ftp_connection.rb → open_connection.rb} +5 -5
- data/lib/pg_export/lib/pg_export/operations/remove_old_dumps_from_ftp.rb +6 -6
- data/lib/pg_export/lib/pg_export/repositories/{ftp_dump_file_repository.rb → gateway_dump_file_repository.rb} +3 -3
- data/lib/pg_export/lib/pg_export/repositories/{ftp_dump_repository.rb → gateway_dump_repository.rb} +7 -7
- data/lib/pg_export/lib/pg_export/transactions/export_dump.rb +8 -8
- data/lib/pg_export/lib/pg_export/transactions/import_dump_interactively.rb +14 -14
- data/lib/pg_export/lib/pg_export/types.rb +1 -1
- data/lib/pg_export/system/boot/interactive.rb +1 -1
- data/lib/pg_export/system/boot/plain.rb +2 -2
- data/lib/pg_export/version.rb +1 -1
- data/pg_export.gemspec +10 -6
- metadata +84 -27
- data/lib/pg_export/lib/pg_export/factories/ftp_adapter_factory.rb +0 -22
- 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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3eb793296ca1e2e22519a8abf1644f88fd06daa02a672d392f318a19128c50cb
|
4
|
+
data.tar.gz: '085a37ec1e0b7cc96f811e73a0a3271086e1c12fba3e6a2da831c6f58a4f9fde'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a3b89d600dc035cca7cdc909b503ac1d62e7844531d5f8a35c8213339968074ccb21d49669a1623f3d616f0aa52c2ccfb1c6c0a54f864e602ffcbe32a43c0886
|
7
|
+
data.tar.gz: 9a93edd9855a3a20d5745491cedbcff104cd8aee180e1c10537c63c129c8ed96933f36d5120476b85812aece2bcaba507391910e282097b5a8555e210a0e209e
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -1,9 +1,12 @@
|
|
1
|
-
sudo: false
|
2
1
|
language: ruby
|
3
2
|
rvm:
|
4
|
-
-
|
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
|
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
|
-
-
|
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
|
-
|
71
|
-
|
72
|
-
|
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
|
-
|
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***", :
|
88
|
-
:
|
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('-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
puts
|
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 { |
|
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
|
8
|
+
include Dry::Types()
|
9
9
|
|
10
10
|
attribute :dump_encryption_key, Strict::String.constrained(size: 16)
|
11
|
-
attribute :
|
12
|
-
attribute :
|
13
|
-
attribute :
|
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['
|
20
|
-
|
21
|
-
|
22
|
-
|
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
|
data/lib/pg_export/container.rb
CHANGED
@@ -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/
|
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
|
-
|
26
|
-
|
27
|
-
|
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/
|
44
|
+
require 'pg_export/lib/pg_export/operations/open_connection'
|
37
45
|
end
|
38
46
|
|
39
47
|
start do
|
40
|
-
use
|
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.
|
53
|
+
register('operations.open_connection') { ::PgExport::Operations::OpenConnection.new }
|
45
54
|
end
|
46
55
|
end
|
47
56
|
end
|
data/lib/pg_export/import.rb
CHANGED
@@ -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
|
9
|
-
class
|
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
|
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
|
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 ||=
|
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
|