ey_cloud_server 1.4.60 → 1.4.61
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 +8 -8
- data/features/step_definitions/mysql.rb +2 -0
- data/lib/ey_backup.rb +1 -1
- data/lib/ey_backup/cli.rb +38 -4
- data/lib/ey_backup/engine.rb +3 -3
- data/lib/ey_backup/engines/mysql_engine.rb +2 -2
- data/lib/ey_backup/engines/postgresql_engine.rb +28 -12
- data/lib/ey_cloud_server/version.rb +1 -1
- data/spec/ey_backup/backup_spec.rb +2 -0
- data/spec/ey_backup/cli_spec.rb +2 -0
- data/spec/ey_backup/mysql_backups_spec.rb +8 -0
- data/spec/ey_backup/postgres_backups_spec.rb +12 -0
- data/spec/helpers.rb +7 -6
- data/spec/log/ey_flex_postgresql_db_thecae.sizes +1 -0
- metadata +4 -4
- data/spec/log/ey_flex_postgresql_db_wanting.sizes +0 -1
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
ODliZWU4ZDUzNjk1NTExYzdiMTJiMjE3MzUxOGI2Y2VjYmUwNzg4ZQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
OWI2Nzg4YWI5ZDFhNGZiNDcwOGM3ZGFmYTE5OTE4NzM2YzMyOGY3Zg==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
YzQxNzY3OTE3YWViZTZlMmFkNTc5ZWJiMWZiYTYyN2FmMDNkYTQyYjk5ZWQ4
|
10
|
+
MGVhOGRmNzVjZDVkMGFjYzFkN2UxMjdlODk3MDczNDVhMjI1MjFjOTg2YmUy
|
11
|
+
ZDRmY2I3YmU2OTk3N2E1MmU2ODc4NjBiMTQzNWNjNzcyYjNhYjI=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
YTRlZjdjYmE2ODk5NTQ0YzE1ODkwOTAwYWM1OWZhMDRiMDhhZmYxZWYxZmQ3
|
14
|
+
ZTkwZWY0ZGRkZTE2MDZlNjU4ZGNlZWRmMzBjNTVmMGUyZmNlOWE2NDZjZjll
|
15
|
+
NDZmYTI4N2ZjZTdjNWE5MDA4NjAwMGE4NjUwODdlODZiODgzMzc=
|
@@ -1,10 +1,12 @@
|
|
1
1
|
Given \
|
2
2
|
/^there is a mysql database \(([^\)]*)\)$/ do |db_key|
|
3
3
|
create_mysql_database(db_key)
|
4
|
+
setup_dna({:db_stack_name => "mysql5_5"})
|
4
5
|
end
|
5
6
|
|
6
7
|
Given \
|
7
8
|
/^the "([^\"]*)" mysql database is dropped$/ do |db_key|
|
8
9
|
db_name = created_mysql_dbs[db_key]
|
9
10
|
drop_mysql_database(db_name)
|
11
|
+
teardown_dna
|
10
12
|
end
|
data/lib/ey_backup.rb
CHANGED
@@ -147,7 +147,7 @@ module EY
|
|
147
147
|
if ! @options.key?(:dbhost) or @options[:dbhost] == nil or @options[:dbhost] == ""
|
148
148
|
@options[:dbhost] = 'localhost'
|
149
149
|
end
|
150
|
-
@engine = engine_class.new(@options[:dbuser], @options[:dbpass], @options[:dbhost], @options[:key_id], @options[:force], @options[:allow_concurrent], @options[:skip_analyze])
|
150
|
+
@engine = engine_class.new(@options[:dbuser], @options[:dbpass], @options[:dbhost], @options[:key_id], @options[:force], @options[:allow_concurrent], @options[:skip_analyze], @options[:log_coordinates])
|
151
151
|
end
|
152
152
|
|
153
153
|
def dispatch
|
data/lib/ey_backup/cli.rb
CHANGED
@@ -9,18 +9,50 @@ module EY
|
|
9
9
|
|
10
10
|
config_path = options[:config] || "/etc/.#{options[:engine]}.backups.yml"
|
11
11
|
|
12
|
-
config_for(config_path).merge(options)
|
12
|
+
options = config_for(config_path).merge(options)
|
13
|
+
options = late_options.merge(options)
|
14
|
+
|
15
|
+
options[:tmp_dir] = '/mnt/tmp' if options[:tmp_dir].nil?
|
16
|
+
options = delayed_engine(File.join(options[:tmp_dir], '/chef/dna.json')).merge(options){|k, v1, v2| v2.nil? ? v1 : v2}
|
17
|
+
abort("Unable to determine database stack from dna; specify the engine with -e") if options[:engine].nil?
|
18
|
+
options
|
13
19
|
end
|
14
20
|
|
15
21
|
def default_options
|
16
22
|
{
|
17
23
|
:command => :new_backup,
|
18
24
|
:format => "gzip",
|
19
|
-
:engine => '
|
25
|
+
:engine => db_stack_name('/etc/chef/dna.json'),
|
20
26
|
:verbose => false,
|
21
27
|
}
|
22
28
|
end
|
23
29
|
|
30
|
+
def late_options
|
31
|
+
{
|
32
|
+
:log_coordinates => false,
|
33
|
+
:skip_analyze => false,
|
34
|
+
:allow_concurrent => false,
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
def delayed_engine(path)
|
39
|
+
{
|
40
|
+
:engine => db_stack_name(path),
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
44
|
+
def db_stack_name(file)
|
45
|
+
|
46
|
+
if File.exist?(file)
|
47
|
+
case %x{cat #{file} | grep db_stack_name}
|
48
|
+
when /mysql/
|
49
|
+
'mysql'
|
50
|
+
when /postgres/
|
51
|
+
'postgresql'
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
24
56
|
def verify_restore
|
25
57
|
res = ''
|
26
58
|
puts "This will overwrite your database, are you sure you would like to proceed (Y/n)?"
|
@@ -118,12 +150,14 @@ module EY
|
|
118
150
|
options[:force] = true
|
119
151
|
end
|
120
152
|
|
121
|
-
|
153
|
+
opts.on("--log_coordinates", "Record MySQL binary log position so backup can be used with replication or Point in Time functions.") do
|
154
|
+
options[:log_coordinates] = true
|
155
|
+
end
|
156
|
+
|
122
157
|
opts.on("--allow_concurrent", "Allow eybackup process to run concurrently with other eybackup processes.") do
|
123
158
|
options[:allow_concurrent] = true
|
124
159
|
end
|
125
160
|
|
126
|
-
options[:skip_analyze] = false
|
127
161
|
opts.on("--skip_analyze", "Skip automatic analyze during PostgreSQL Restore operations.") do
|
128
162
|
options[:skip_analyze] = true
|
129
163
|
end
|
data/lib/ey_backup/engine.rb
CHANGED
@@ -3,7 +3,7 @@ module EY
|
|
3
3
|
class Engine < Base
|
4
4
|
include Spawner
|
5
5
|
|
6
|
-
attr_reader :username, :password, :host, :key_id, :force, :allow_concurrent, :skip_analyze
|
6
|
+
attr_reader :username, :password, :host, :key_id, :force, :allow_concurrent, :skip_analyze, :log_coordinates
|
7
7
|
|
8
8
|
def self.label
|
9
9
|
@label
|
@@ -26,8 +26,8 @@ module EY
|
|
26
26
|
EY::Backup.logger.fatal("Unknown database engine: #{label}")
|
27
27
|
end
|
28
28
|
|
29
|
-
def initialize(username, password, host, key_id, force, allow_concurrent, skip_analyze)
|
30
|
-
@username, @password, @host, @key_id, @force, @allow_concurrent, @skip_analyze
|
29
|
+
def initialize(username, password, host, key_id, force, allow_concurrent, skip_analyze, log_coordinates)
|
30
|
+
@username, @password, @host, @key_id, @force, @allow_concurrent, @skip_analyze, @log_coordinates = username, password, host, key_id, force, allow_concurrent, skip_analyze, log_coordinates
|
31
31
|
end
|
32
32
|
|
33
33
|
def block_concurrent(db = nil)
|
@@ -57,14 +57,14 @@ module EY
|
|
57
57
|
end
|
58
58
|
|
59
59
|
def server_id
|
60
|
-
if log_bin_on?
|
60
|
+
if log_bin_on? and log_coordinates
|
61
61
|
stdout = %x{mysql #{username_option} #{host_option} -BN -e"select @@global.server_id"}
|
62
62
|
"echo '-- Server_id: #{stdout.strip}' && "
|
63
63
|
end
|
64
64
|
end
|
65
65
|
|
66
66
|
def master_data_option
|
67
|
-
"--master-data=2" if log_bin_on?
|
67
|
+
"--master-data=2" if log_bin_on? and log_coordinates
|
68
68
|
end
|
69
69
|
|
70
70
|
def databases_option(db)
|
@@ -6,7 +6,7 @@ module EY
|
|
6
6
|
def dump(database_name, basename)
|
7
7
|
file = basename + '.dump'
|
8
8
|
|
9
|
-
command = "PGPASSWORD='#{password}' pg_dump -h #{host} --create --format=c -
|
9
|
+
command = "PGPASSWORD='#{password}' pg_dump -h #{host} --create --format=c -U#{username} #{database_name} "
|
10
10
|
|
11
11
|
if gpg?
|
12
12
|
command << " | " << GPGEncryptor.command_for(key_id)
|
@@ -25,26 +25,32 @@ module EY
|
|
25
25
|
if file =~ /.gpz$/ # GPG?
|
26
26
|
abort "\nCannot restore a GPG backup directly; decrypt the file (#{file}) using your key and then load with pg_restore.
|
27
27
|
To decrypt a backup: https://support.cloud.engineyard.com/hc/en-us/articles/205413948-Use-PGP-Encrypted-Database-Backups-with-Engine-Yard-Cloud#restore
|
28
|
-
Once decrypted, restore with: `pg_restore -h #{host} --format=c --clean -
|
28
|
+
Once decrypted, restore with: `pg_restore -h #{host} --format=c --clean -U#{username} -d #{database_name} <filename>`\n\n"
|
29
29
|
end
|
30
30
|
|
31
31
|
cycle_database(database_name)
|
32
|
+
|
33
|
+
# Exclude Extension Comments
|
34
|
+
toc_file = "#{file}.toc"
|
35
|
+
table_of_contents(file, toc_file)
|
32
36
|
|
33
37
|
command = "cat #{file}"
|
34
38
|
|
35
|
-
command << " | PGPASSWORD='#{password}' pg_restore -h #{host} --format=c -
|
39
|
+
command << " | PGPASSWORD='#{password}' pg_restore -L #{toc_file} -h #{host} --format=c -U#{username} -d #{database_name}"
|
36
40
|
|
37
41
|
run(command, database_name)
|
38
42
|
|
43
|
+
system("rm #{toc_file}") if File.exists?(toc_file)
|
44
|
+
|
39
45
|
# Analyze database unless disabled
|
40
46
|
unless skip_analyze
|
41
47
|
verbose "Analyzing database '#{database_name}', use --skip-analyze to skip this step."
|
42
|
-
%x{PGPASSWORD='#{password}' vacuumdb -h #{host} -
|
48
|
+
%x{PGPASSWORD='#{password}' vacuumdb -h #{host} -U#{username} -d #{database_name} --analyze-only}
|
43
49
|
end
|
44
50
|
end
|
45
51
|
|
46
52
|
def check_connections(database_name)
|
47
|
-
active_connections = %x{PGPASSWORD='#{password}' psql -U
|
53
|
+
active_connections = %x{PGPASSWORD='#{password}' psql -U#{username} -h #{host} -t postgres -c "select count(*) from pg_stat_activity where datname='#{database_name}';"}
|
48
54
|
|
49
55
|
if active_connections.to_i > 0
|
50
56
|
res = ''
|
@@ -64,13 +70,13 @@ module EY
|
|
64
70
|
end
|
65
71
|
|
66
72
|
def cancel_connections(database_name)
|
67
|
-
%x{psql -U
|
73
|
+
%x{psql -U#{username} -h #{host} postgres -c"SELECT pg_terminate_backend(pg_stat_activity.pid)
|
68
74
|
FROM pg_stat_activity
|
69
75
|
WHERE pg_stat_activity.datname = '#{database_name}';"}
|
70
76
|
end
|
71
77
|
|
72
78
|
def drop_database(database_name)
|
73
|
-
command = "PGPASSWORD='#{password}' dropdb -h #{host} -
|
79
|
+
command = "PGPASSWORD='#{password}' dropdb -h #{host} -U#{username} #{database_name}"
|
74
80
|
verbose "Dropping Database with: #{command}"
|
75
81
|
%x{#{command}}
|
76
82
|
end
|
@@ -82,14 +88,23 @@ module EY
|
|
82
88
|
end
|
83
89
|
|
84
90
|
def check_if_replica
|
85
|
-
|
91
|
+
command = "PGPASSWORD='#{password}' psql -U#{username} -h #{host} -t -c 'select pg_is_in_recovery()' postgres| head -n 1"
|
92
|
+
verbose "Checking for replica state with: #{command}"
|
93
|
+
stdout = %x{#{command}}
|
86
94
|
unless stdout.chomp =~ /^\W*f$/
|
87
95
|
EY::Backup.logger.fatal(%Q{ERROR: Target host: '#{host}' is currently a replica in recovery mode; restore operations need to be processed against the master.})
|
88
96
|
end
|
89
97
|
end
|
90
98
|
|
99
|
+
def table_of_contents(file, toc_file)
|
100
|
+
command = %Q{pg_restore -l #{file} | sed -e 's/^\\\(.* COMMENT - EXTENSION .*\\\)/;\\1/g' \
|
101
|
+
-e 's/^\\\(.* rdsadmin$\\\)/;\\1/g' > #{toc_file}}
|
102
|
+
verbose "Creating table of contents: #{command}"
|
103
|
+
%x{#{command}}
|
104
|
+
end
|
105
|
+
|
91
106
|
def create_command(database_name)
|
92
|
-
|
107
|
+
command="PGPASSWORD='#{password}' psql -U#{username} -h #{host} -t postgres -c \"SELECT 'CREATE DATABASE ' || datname ||
|
93
108
|
' WITH OWNER ' || pg_user.usename ||
|
94
109
|
CASE (select pg_encoding_to_char(encoding) from pg_database where datname='template1')
|
95
110
|
WHEN pg_encoding_to_char(encoding)
|
@@ -103,8 +118,9 @@ module EY
|
|
103
118
|
FROM pg_database
|
104
119
|
INNER JOIN pg_user
|
105
120
|
ON pg_user.usesysid = pg_database.datdba
|
106
|
-
WHERE datname = '#{database_name}'"
|
107
|
-
}
|
121
|
+
WHERE datname = '#{database_name}'\""
|
122
|
+
verbose "Getting create info: #{command}"
|
123
|
+
%x{#{command}}
|
108
124
|
end
|
109
125
|
|
110
126
|
def cycle_database(database_name)
|
@@ -114,7 +130,7 @@ module EY
|
|
114
130
|
else
|
115
131
|
check_connections(database_name)
|
116
132
|
drop_database(database_name)
|
117
|
-
%x{PGPASSWORD='#{password}' psql -U
|
133
|
+
%x{PGPASSWORD='#{password}' psql -U#{username} -h #{host} -t postgres -c "#{create_cmd}"}
|
118
134
|
end
|
119
135
|
end
|
120
136
|
|
@@ -3,10 +3,12 @@ require File.dirname(__FILE__) + '/spec_helper'
|
|
3
3
|
describe EY::Backup do
|
4
4
|
before(:each) do
|
5
5
|
@db_name = create_mysql_database('first')
|
6
|
+
setup_dna({:db_stack_name => "mysql5_5"})
|
6
7
|
end
|
7
8
|
|
8
9
|
after(:each) do
|
9
10
|
drop_mysql_database(@db_name)
|
11
|
+
teardown_dna
|
10
12
|
end
|
11
13
|
|
12
14
|
describe "#list" do
|
data/spec/ey_backup/cli_spec.rb
CHANGED
@@ -3,10 +3,12 @@ require File.dirname(__FILE__) + '/spec_helper'
|
|
3
3
|
describe "MySQL Backups" do
|
4
4
|
before(:each) do
|
5
5
|
@db_name = create_mysql_database('first')
|
6
|
+
setup_dna({:db_stack_name => "mysql5_5"})
|
6
7
|
end
|
7
8
|
|
8
9
|
after(:each) do
|
9
10
|
drop_mysql_database(@db_name)
|
11
|
+
teardown_dna
|
10
12
|
end
|
11
13
|
|
12
14
|
describe "--quiet" do
|
@@ -3,11 +3,13 @@ require File.dirname(__FILE__) + '/spec_helper'
|
|
3
3
|
describe "MySQL Backups" do
|
4
4
|
before(:each) do
|
5
5
|
@db_name = create_mysql_database('first')
|
6
|
+
setup_dna({:db_stack_name => "mysql5_5"})
|
6
7
|
mk_tmp
|
7
8
|
end
|
8
9
|
|
9
10
|
after(:each) do
|
10
11
|
drop_mysql_database(@db_name)
|
12
|
+
teardown_dna
|
11
13
|
end
|
12
14
|
|
13
15
|
it "makes a backup" do
|
@@ -148,12 +150,14 @@ end
|
|
148
150
|
describe "MySQL Backups" do
|
149
151
|
before(:each) do
|
150
152
|
@dbs = [create_mysql_database('first'), create_mysql_database('second')]
|
153
|
+
setup_dna({:db_stack_name => "mysql5_5"})
|
151
154
|
end
|
152
155
|
|
153
156
|
after(:each) do
|
154
157
|
@dbs.each do |db|
|
155
158
|
drop_mysql_database(db)
|
156
159
|
end
|
160
|
+
teardown_dna
|
157
161
|
end
|
158
162
|
|
159
163
|
it "makes a backup" do
|
@@ -172,10 +176,12 @@ describe "a multi-region backup" do
|
|
172
176
|
describe "in japan!" do
|
173
177
|
before(:each) do
|
174
178
|
@db_name = create_mysql_database('speaking_japanese', 'ap-northeast-1')
|
179
|
+
setup_dna({:db_stack_name => "mysql5_5"})
|
175
180
|
end
|
176
181
|
|
177
182
|
after(:each) do
|
178
183
|
drop_mysql_database(@db_name)
|
184
|
+
teardown_dna
|
179
185
|
end
|
180
186
|
|
181
187
|
it "makes a split backup" do
|
@@ -211,10 +217,12 @@ describe "a multi-region backup" do
|
|
211
217
|
describe "in europe!" do
|
212
218
|
before(:each) do
|
213
219
|
@db_name = create_mysql_database('speaking_esperanto', 'eu-west-1')
|
220
|
+
setup_dna({:db_stack_name => "mysql5_5"})
|
214
221
|
end
|
215
222
|
|
216
223
|
after(:each) do
|
217
224
|
drop_mysql_database(@db_name)
|
225
|
+
teardown_dna
|
218
226
|
end
|
219
227
|
|
220
228
|
it "makes a split backup" do
|
@@ -3,10 +3,12 @@ require File.dirname(__FILE__) + '/spec_helper'
|
|
3
3
|
describe "Postgres Backups" do
|
4
4
|
before(:each) do
|
5
5
|
@db_name = create_postgresql_database('first')
|
6
|
+
setup_dna({:db_stack_name => "postgres9_5"})
|
6
7
|
end
|
7
8
|
|
8
9
|
after(:each) do
|
9
10
|
drop_postgresql_database(@db_name)
|
11
|
+
teardown_dna
|
10
12
|
end
|
11
13
|
|
12
14
|
it "makes a custom format backup" do
|
@@ -18,6 +20,16 @@ describe "Postgres Backups" do
|
|
18
20
|
|
19
21
|
stdout.should match(/0:#{@db_name}.*\.dump$/)
|
20
22
|
end
|
23
|
+
|
24
|
+
it "makes a custom backup and detects that the db is Postgres" do
|
25
|
+
EY::Backup.run(["-c", backup_config_file])
|
26
|
+
|
27
|
+
reset_logger
|
28
|
+
|
29
|
+
EY::Backup.run(["-c", backup_config_file, "-l", @db_name, "-e", "postgresql"])
|
30
|
+
|
31
|
+
stdout.should match(/0:#{@db_name}.*\.dump$/)
|
32
|
+
end
|
21
33
|
|
22
34
|
it "makes a split backup" do
|
23
35
|
EY::Backup.run(["-c", backup_config_file, "-e", "postgresql", "-s", "100"])
|
data/spec/helpers.rb
CHANGED
@@ -73,16 +73,17 @@ module Helpers
|
|
73
73
|
end
|
74
74
|
end
|
75
75
|
|
76
|
-
def teardown_dna(
|
77
|
-
FileUtils.rm_f("#{tmp_dir}/dna.json")
|
76
|
+
def teardown_dna()
|
77
|
+
FileUtils.rm_f("#{tmp_dir}/chef/dna.json")
|
78
|
+
FileUtils.rm_r("#{tmp_dir}/chef")
|
78
79
|
end
|
79
80
|
|
80
81
|
def setup_dna(data)
|
81
|
-
FileUtils.mkdir_p("#{tmp_dir}")
|
82
|
-
if File.exist?("#{tmp_dir}/dna.json")
|
83
|
-
FileUtils.rm("#{tmp_dir}/dna.json")
|
82
|
+
FileUtils.mkdir_p("#{tmp_dir}/chef")
|
83
|
+
if File.exist?("#{tmp_dir}/chef/dna.json")
|
84
|
+
FileUtils.rm("#{tmp_dir}/chef/dna.json")
|
84
85
|
end
|
85
|
-
File.open("#{tmp_dir}/dna.json", "w") do |f|
|
86
|
+
File.open("#{tmp_dir}/chef/dna.json", "w") do |f|
|
86
87
|
f.puts data.to_json
|
87
88
|
end
|
88
89
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
2017-08-29 15:44:07 -0400 1.7 KB
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ey_cloud_server
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.4.
|
4
|
+
version: 1.4.61
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- EngineYard
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-08-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|
@@ -279,7 +279,7 @@ files:
|
|
279
279
|
- spec/gpg.public
|
280
280
|
- spec/gpg.sekrit
|
281
281
|
- spec/helpers.rb
|
282
|
-
- spec/log/
|
282
|
+
- spec/log/ey_flex_postgresql_db_thecae.sizes
|
283
283
|
- spec/snapshot_minder_spec.rb
|
284
284
|
- spec/spec_helper.rb
|
285
285
|
homepage: http://developer.engineyard.com
|
@@ -320,7 +320,7 @@ test_files:
|
|
320
320
|
- spec/gpg.public
|
321
321
|
- spec/gpg.sekrit
|
322
322
|
- spec/helpers.rb
|
323
|
-
- spec/log/
|
323
|
+
- spec/log/ey_flex_postgresql_db_thecae.sizes
|
324
324
|
- spec/snapshot_minder_spec.rb
|
325
325
|
- spec/spec_helper.rb
|
326
326
|
- features/downloading_a_mysql_backup.feature
|
@@ -1 +0,0 @@
|
|
1
|
-
2017-05-17 02:10:11 -0400 1.7 KB
|