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