ey_cloud_server 1.4.54 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -6,7 +6,7 @@ module EY
6
6
  def dump(database_name, basename)
7
7
  file = basename + '.sql'
8
8
 
9
- command = "mysqldump #{username_option} #{host_option} #{single_transaction_option(database_name)} #{routines_option} #{master_data_option} #{databases_option(database_name)} 2> /tmp/eybackup.$$.dumperr"
9
+ command = "( #{server_id} mysqldump #{username_option} #{host_option} #{single_transaction_option(database_name)} #{routines_option} #{master_data_option} #{databases_option(database_name)} ) "
10
10
 
11
11
  if gpg?
12
12
  command << " | " << GPGEncryptor.command_for(key_id)
@@ -17,6 +17,8 @@ module EY
17
17
  end
18
18
 
19
19
  command << " > #{file}"
20
+
21
+ block_concurrent(database_name) unless allow_concurrent
20
22
 
21
23
  run(command, database_name)
22
24
 
@@ -27,14 +29,16 @@ module EY
27
29
  command = "cat #{file}"
28
30
 
29
31
  if file =~ /.gpz$/ # GPG?
30
- abort "Cannot restore a GPG backup directly; decrypt the file (#{file}) using your key and then load using the mysql client."
32
+ abort "\nCannot restore a GPG backup directly; decrypt the file (#{file}) using your key and then load using the mysql client.
33
+ To decrypt a backup: https://support.cloud.engineyard.com/hc/en-us/articles/205413948-Use-PGP-Encrypted-Database-Backups-with-Engine-Yard-Cloud#restore
34
+ Once decrypted, restore with: `gunzip -f < <filename> | mysql #{username_option} #{host_option} #{database_name}`\n\n"
31
35
  else
32
36
  command << " | " << GZipper.gunzip
33
37
  end
34
38
 
35
39
  cycle_database(database_name)
36
40
 
37
- command << " | mysql #{username_option} #{host_option} #{database_name} 2> /tmp/eybackup.$$.dumperr"
41
+ command << " | mysql #{username_option} #{host_option} #{database_name} "
38
42
 
39
43
  run(command, database_name)
40
44
  end
@@ -52,12 +56,19 @@ module EY
52
56
  "--routines"
53
57
  end
54
58
 
59
+ def server_id
60
+ if log_bin_on? and log_coordinates
61
+ stdout = %x{mysql #{username_option} #{host_option} -BN -e"select @@global.server_id"}
62
+ "echo '-- Server_id: #{stdout.strip}' && "
63
+ end
64
+ end
65
+
55
66
  def master_data_option
56
- "--master-data=2" if log_bin_on?
67
+ "--master-data=2" if log_bin_on? and log_coordinates
57
68
  end
58
69
 
59
70
  def databases_option(db)
60
- "--add-drop-database --databases #{db}"
71
+ "#{db}"
61
72
  end
62
73
 
63
74
  def host_option
@@ -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 -Upostgres #{database_name} 2> /tmp/eybackup.$$.dumperr"
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)
@@ -15,6 +15,7 @@ module EY
15
15
 
16
16
  command << " > #{file}"
17
17
 
18
+ block_concurrent(database_name) unless allow_concurrent
18
19
  run(command, database_name)
19
20
 
20
21
  file
@@ -22,25 +23,39 @@ module EY
22
23
 
23
24
  def load(database_name, file)
24
25
  if file =~ /.gpz$/ # GPG?
25
- abort "Cannot restore a GPG backup directly; decrypt the file (#{file}) using your key and then load with pg_restore."
26
+ abort "\nCannot restore a GPG backup directly; decrypt the file (#{file}) using your key and then load with pg_restore.
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 -U#{username} -d #{database_name} <filename>`\n\n"
26
29
  end
27
30
 
28
31
  cycle_database(database_name)
32
+
33
+ # Exclude Extension Comments
34
+ toc_file = "#{file}.toc"
35
+ table_of_contents(file, toc_file)
29
36
 
30
37
  command = "cat #{file}"
31
38
 
32
- command << " | PGPASSWORD='#{password}' pg_restore -h #{host} --format=c -Upostgres -d #{database_name} 2> /tmp/eybackup.$$.dumperr"
39
+ command << " | PGPASSWORD='#{password}' pg_restore -L #{toc_file} -h #{host} --format=c -U#{username} -d #{database_name}"
33
40
 
34
41
  run(command, database_name)
42
+
43
+ system("rm #{toc_file}") if File.exists?(toc_file)
44
+
45
+ # Analyze database unless disabled
46
+ unless skip_analyze
47
+ verbose "Analyzing database '#{database_name}', use --skip-analyze to skip this step."
48
+ %x{PGPASSWORD='#{password}' vacuumdb -h #{host} -U#{username} -d #{database_name} --analyze-only}
49
+ end
35
50
  end
36
51
 
37
52
  def check_connections(database_name)
38
- active_connections = %x{PGPASSWORD='#{password}' psql -U postgres -h #{host} -t -c "select count(*) from pg_stat_activity where datname='#{database_name}';"}
53
+ active_connections = %x{PGPASSWORD='#{password}' psql -U#{username} -h #{host} -t postgres -c "select count(*) from pg_stat_activity where datname='#{database_name}';"}
39
54
 
40
55
  if active_connections.to_i > 0
41
56
  res = ''
42
57
  unless force
43
- puts "There are currently #{stdout.string.to_i} connections on database: '#{database_name}'; can I kill these to continue (Y/n):"
58
+ puts "There are currently #{active_connections} connections on database: '#{database_name}'; can I kill these to continue (Y/n):"
44
59
  Timeout::timeout(30){
45
60
  res = gets.strip
46
61
  }
@@ -55,13 +70,13 @@ module EY
55
70
  end
56
71
 
57
72
  def cancel_connections(database_name)
58
- %x{psql -U postgres -h #{host} -c"SELECT pg_terminate_backend(pg_stat_activity.pid)
73
+ %x{psql -U#{username} -h #{host} postgres -c"SELECT pg_terminate_backend(pg_stat_activity.pid)
59
74
  FROM pg_stat_activity
60
75
  WHERE pg_stat_activity.datname = '#{database_name}';"}
61
76
  end
62
77
 
63
78
  def drop_database(database_name)
64
- command = "PGPASSWORD='#{password}' dropdb -h #{host} -Upostgres #{database_name}"
79
+ command = "PGPASSWORD='#{password}' dropdb -h #{host} -U#{username} #{database_name}"
65
80
  verbose "Dropping Database with: #{command}"
66
81
  %x{#{command}}
67
82
  end
@@ -73,14 +88,23 @@ module EY
73
88
  end
74
89
 
75
90
  def check_if_replica
76
- stdout = %x{PGPASSWORD='#{password}' psql -U postgres -h #{host} -t -c "select pg_is_in_recovery()"| head -n 1}
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}}
77
94
  unless stdout.chomp =~ /^\W*f$/
78
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.})
79
96
  end
80
97
  end
81
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
+
82
106
  def create_command(database_name)
83
- %x{PGPASSWORD='#{password}' psql -U postgres -h #{host} -t -c "SELECT 'CREATE DATABASE ' || datname ||
107
+ command="PGPASSWORD='#{password}' psql -U#{username} -h #{host} -t postgres -c \"SELECT 'CREATE DATABASE ' || datname ||
84
108
  ' WITH OWNER ' || pg_user.usename ||
85
109
  CASE (select pg_encoding_to_char(encoding) from pg_database where datname='template1')
86
110
  WHEN pg_encoding_to_char(encoding)
@@ -94,8 +118,9 @@ module EY
94
118
  FROM pg_database
95
119
  INNER JOIN pg_user
96
120
  ON pg_user.usesysid = pg_database.datdba
97
- WHERE datname = '#{database_name}'"
98
- }
121
+ WHERE datname = '#{database_name}'\""
122
+ verbose "Getting create info: #{command}"
123
+ %x{#{command}}
99
124
  end
100
125
 
101
126
  def cycle_database(database_name)
@@ -105,7 +130,7 @@ module EY
105
130
  else
106
131
  check_connections(database_name)
107
132
  drop_database(database_name)
108
- %x{PGPASSWORD='#{password}' psql -U postgres -h #{host} -t -c "#{create_cmd}"}
133
+ %x{PGPASSWORD='#{password}' psql -U#{username} -h #{host} -t postgres -c "#{create_cmd}"}
109
134
  end
110
135
  end
111
136
 
@@ -16,8 +16,10 @@ module EY
16
16
  end
17
17
 
18
18
  def run
19
- info "Restoring #{@database.name}"
19
+
20
20
  backup = download
21
+ mode = backup.basename =~ /.gpz$/ ? "Downloading" : "Restoring"
22
+ info "#{mode} #{@database.name}"
21
23
  backup.load!
22
24
  backup.remove_joined_file!
23
25
  end
@@ -1,8 +1,15 @@
1
+ class String
2
+ def truncate(limit = 1)
3
+ self.match(%r{^(.{0,#{limit}})})[1]
4
+ end
5
+ end
6
+
1
7
  module EY
2
8
  module Backup
3
9
  class Logger
4
10
  extend Forwardable
5
11
  require 'shellwords'
12
+ require 'fileutils'
6
13
 
7
14
  attr_accessor :stdout, :stderr
8
15
 
@@ -22,21 +29,22 @@ module EY
22
29
 
23
30
  def push_dashboard_alert(message, alert_level, db = nil)
24
31
  message.gsub!("\n", '\n')
32
+ message = Shellwords.escape(message).truncate(255)
25
33
  type="process-dbbackup"
26
34
  type = type + " #{db}" unless db.nil?
27
35
  full_txt= "Severity: #{alert_level}\n" \
28
36
  + "Time: #{Time.now.to_i}\n" \
29
37
  + "Type: #{type}\n" \
30
- + "Plugin: exec\n" \
31
- + "raw_message: '#{message}'"
38
+ + "Plugin: exec\n"
32
39
  full_txt = Shellwords.escape(full_txt)
40
+ full_txt += "raw_message:\\ \\'#{message}\\'"
33
41
  alert_command = %Q(echo #{full_txt} | /engineyard/bin/ey-alert.rb 2>&1)
34
42
  verbose "Sending dashboard alert"
35
43
  system(alert_command)
36
44
  end
37
45
 
38
46
  def info(msg)
39
- puts "#{Time.now} #{msg}"
47
+ stdout.puts "#{Time.now} #{msg}"
40
48
  end
41
49
 
42
50
  def verbose(msg)
@@ -46,24 +54,48 @@ module EY
46
54
  def set_verbose()
47
55
  @verbose = true
48
56
  end
57
+
58
+ def set_log_path=(path)
59
+ @status_path = path
60
+ FileUtils.mkdir_p(@status_path)
61
+ end
49
62
 
50
63
  def say(msg, newline = true)
51
64
  newline ? info(msg) : stdout.print(msg)
52
65
  end
53
66
 
54
- def okay(msg, db = nil)
55
- stderr.puts("#{Time.now} OKAY: #{msg}")
56
- # push_dashboard_alert(msg, "OKAY", db), we don't push OKAY alerts, we push a summary alert instead.
67
+ def okay(db, size)
68
+ filepath = File.join(@status_path, "#{db}.sizes")
69
+ %x{LOG=$(tail -n 100 #{filepath}); echo "$LOG" > #{filepath}} if File.exists?(filepath)
70
+ %x{echo "#{Time.now()} #{size}" >> #{filepath}}
71
+ msg = "Backup successful for '#{db}' after previous failure."
72
+ push_dashboard_alert(msg, 'OKAY', db) if clear_alert?(db)
57
73
  end
58
74
 
59
75
  def warn(msg, db = nil)
60
- stderr.puts("#{Time.now} WARNING: #{msg}")
76
+ stdout.puts("#{Time.now} WARNING: #{msg}")
77
+ set_alert(msg, db) unless db.nil?
61
78
  push_dashboard_alert(msg, "WARNING", db)
62
79
  end
63
80
 
64
81
  def error(msg, db = nil)
65
- stderr.puts("#{Time.now} ERROR: #{msg}")
66
- push_dashboard_alert("#{msg}. Details at /var/log/eybackup.log.", "FAILURE", db)
82
+ stdout.puts("#{Time.now} ERROR: #{msg}")
83
+ set_alert(msg, db) unless db.nil?
84
+ push_dashboard_alert("#{msg} Details at /var/log/eybackup.log.", "FAILURE", db)
85
+ end
86
+
87
+ def set_alert(msg, db)
88
+ fullPath = File.join(@status_path, "#{db}.alert")
89
+ File.open(fullPath, 'a') { |file| file.puts "#{Time.now}: #{msg}"}
90
+ end
91
+
92
+ def clear_alert?(db)
93
+ begin
94
+ File.delete(File.join(@status_path, "#{db}.alert"))
95
+ true
96
+ rescue Errno::ENOENT
97
+ false
98
+ end
67
99
  end
68
100
 
69
101
  def exception(type, msg)
@@ -71,7 +103,7 @@ module EY
71
103
  end
72
104
 
73
105
  def debug(msg)
74
- stderr.puts("#{Time.now} DEBUG: #{msg}")
106
+ stdout.puts("#{Time.now} DEBUG: #{msg}")
75
107
  end
76
108
 
77
109
  end
@@ -5,7 +5,7 @@ module EY
5
5
  include Logging
6
6
 
7
7
  CHUNK_SIZE = 1024 * 64
8
- MAX_FILE_SIZE = (4.5*1024*1024*1024).to_i #4.5GB
8
+ MAX_FILE_SIZE = (4.9*1024*1024*1024*1024).to_i #4.9TB
9
9
 
10
10
  def self.dump(file, split_size)
11
11
  split_size ||= MAX_FILE_SIZE
@@ -42,14 +42,11 @@ module EY
42
42
  pid, stdin, stdout, stderr = Open4.popen4("bash -o pipefail -c #{escaped_command}")
43
43
  pid, status = Process::waitpid2(pid)
44
44
 
45
- verbose "stdout: #{stdout.read}"
46
- verbose "stderr: #{stderr.read}"
47
45
  verbose "status: #{status}"
48
46
 
49
47
  if ! status.success?
50
- dumperr = File.exists?("/tmp/eybackup.#{pid}.dumperr") ? File.read("/tmp/eybackup.#{pid}.dumperr") : status
51
- err_msg = "DB dump failed. The error returned was: #{dumperr}"
52
- verbose "#{db} backup failed: #{err_msg}"
48
+ dumperr = File.exists?("/tmp/eybackup.#{pid}.dumperr") ? File.read("/tmp/eybackup.#{pid}.dumperr") : "#{status}: #{stderr.read.chomp}: #{stdout.read.chomp}"
49
+ err_msg = "#{db} backup failed! The error returned was: #{dumperr}"
53
50
  error(err_msg, db)
54
51
  end
55
52
 
data/lib/ey_backup.rb CHANGED
@@ -44,6 +44,7 @@ module EY
44
44
  class << self
45
45
  attr_accessor :logger
46
46
  attr_accessor :tmp_dir
47
+ attr_accessor :log_dir
47
48
  end
48
49
 
49
50
  def self.run(argv = ARGV)
@@ -96,11 +97,12 @@ module EY
96
97
  if @options[:db].nil? || @options[:db].empty?
97
98
  @options[:databases]
98
99
  else
99
- [@options[:db]]
100
+ [@options[:db]].flatten
100
101
  end
101
102
  end
102
103
 
103
104
  def setup
105
+ setup_log_dir
104
106
  setup_logger
105
107
  setup_tmp_dir
106
108
  setup_backend
@@ -117,6 +119,7 @@ module EY
117
119
  EY::Backup.logger.set_verbose
118
120
  end
119
121
  end
122
+ EY::Backup.logger.set_log_path=EY::Backup.log_dir
120
123
  end
121
124
 
122
125
  def setup_tmp_dir
@@ -126,6 +129,14 @@ module EY
126
129
  EY::Backup.tmp_dir = "/mnt/tmp"
127
130
  end
128
131
  end
132
+
133
+ def setup_log_dir
134
+ if @options[:log_dir]
135
+ EY::Backup.log_dir = @options[:log_dir]
136
+ else
137
+ EY::Backup.log_dir = "/var/log/engineyard/eybackup"
138
+ end
139
+ end
129
140
 
130
141
  def setup_backend
131
142
  @backend = Backend.new(@options[:aws_secret_id], @options[:aws_secret_key], @options[:region], @options[:backup_bucket])
@@ -136,7 +147,7 @@ module EY
136
147
  if ! @options.key?(:dbhost) or @options[:dbhost] == nil or @options[:dbhost] == ""
137
148
  @options[:dbhost] = 'localhost'
138
149
  end
139
- @engine = engine_class.new(@options[:dbuser], @options[:dbpass], @options[:dbhost], @options[:key_id], @options[:force])
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])
140
151
  end
141
152
 
142
153
  def dispatch
@@ -1,5 +1,5 @@
1
1
  module EY
2
2
  module CloudServer
3
- VERSION = '1.4.54'
3
+ VERSION = '1.5.0'
4
4
  end
5
5
  end
@@ -0,0 +1,11 @@
1
+ ---
2
+ tmp_dir:
3
+ data_json:
4
+ mysql_user: jenkins
5
+ mysql_password: jenkins
6
+ mysql_host: localhost
7
+ postgresql_user: postgres
8
+ postgresql_password: postgres
9
+ postgresql_host: localhost
10
+ aws_secret_id: 'abcd123.id'
11
+ aws_secret_key: 'abcd123.key'
@@ -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
@@ -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
@@ -125,17 +127,37 @@ describe "MySQL Backups" do
125
127
  run_sql("SELECT * FROM `bar`;", @db_name).should be_true
126
128
  FileUtils.rm(file)
127
129
  end
130
+
131
+ it 'detects a backup failure due to an invalid view definition and reports it to stdout' do
132
+
133
+ run_sql("CREATE TABLE `foo` (`id` int(11) NOT NULL auto_increment, PRIMARY KEY(`id`));", @db_name).should be_truthy
134
+ run_sql("CREATE TABLE `bar` (`id` int(11) NOT NULL auto_increment, PRIMARY KEY(`id`));", @db_name).should be_truthy
135
+ run_sql("CREATE view `vw_foobar` as select `foo`.`id` as `foo_id`, `bar`.`id` as `bar_id` from `foo` inner join `bar` on `foo`.`id` = `bar`.`id`;", @db_name).should be_truthy
136
+ run_sql("DROP TABLE `bar`;", @db_name).should be_truthy
137
+
138
+ reset_logger
139
+
140
+ EY::Backup.run(["-c", backup_config_file])
141
+ stdout.should match(/mysqldump: Couldn't execute 'SHOW FIELDS FROM `vw_foobar`'/)
142
+
143
+ files = Dir["#{EY::Backup.tmp_dir}/*#{@db_name}*"]
144
+
145
+ files.size.should == 1
146
+ FileUtils.rm(files.first)
147
+ end
128
148
  end
129
149
 
130
150
  describe "MySQL Backups" do
131
151
  before(:each) do
132
152
  @dbs = [create_mysql_database('first'), create_mysql_database('second')]
153
+ setup_dna({:db_stack_name => "mysql5_5"})
133
154
  end
134
155
 
135
156
  after(:each) do
136
157
  @dbs.each do |db|
137
158
  drop_mysql_database(db)
138
159
  end
160
+ teardown_dna
139
161
  end
140
162
 
141
163
  it "makes a backup" do
@@ -154,10 +176,12 @@ describe "a multi-region backup" do
154
176
  describe "in japan!" do
155
177
  before(:each) do
156
178
  @db_name = create_mysql_database('speaking_japanese', 'ap-northeast-1')
179
+ setup_dna({:db_stack_name => "mysql5_5"})
157
180
  end
158
181
 
159
182
  after(:each) do
160
183
  drop_mysql_database(@db_name)
184
+ teardown_dna
161
185
  end
162
186
 
163
187
  it "makes a split backup" do
@@ -193,10 +217,12 @@ describe "a multi-region backup" do
193
217
  describe "in europe!" do
194
218
  before(:each) do
195
219
  @db_name = create_mysql_database('speaking_esperanto', 'eu-west-1')
220
+ setup_dna({:db_stack_name => "mysql5_5"})
196
221
  end
197
222
 
198
223
  after(:each) do
199
224
  drop_mysql_database(@db_name)
225
+ teardown_dna
200
226
  end
201
227
 
202
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
@@ -19,18 +19,28 @@ module Helpers
19
19
  @mock_environment_name => {:id => 1}
20
20
  }))
21
21
 
22
- FileUtils.mkdir_p(tmp_dir)
23
- Dir.glob("#{tmp_dir}/*").each do |f|
22
+ create_or_clean_dir(tmp_dir)
23
+ create_or_clean_dir(log_dir)
24
+
25
+ # FileUtils.mkdir_p(tmp_dir)
26
+ # FileUtils.mkdir_p(log_dir)
27
+ # Dir.glob("#{tmp_dir}/*").each do |f|
28
+ # FileUtils.rm(f)
29
+ # end
30
+ stub_configs
31
+ end
32
+
33
+ def create_or_clean_dir(dir)
34
+ FileUtils.mkdir_p(dir)
35
+ Dir.glob("#{dir}/*").each do |f|
24
36
  FileUtils.rm(f)
25
37
  end
26
-
27
- stub_configs
28
38
  end
29
39
 
30
40
  def stub_configs
31
41
  #print "in stub_configs: #{YAML::dump(@database_config)}, #{YAML::dump(spec_config)}\n"
32
42
  config = @database_config || spec_config
33
- config = config.merge({ :tmp_dir => tmp_dir })
43
+ config = config.merge({ :tmp_dir => tmp_dir, :log_dir => log_dir })
34
44
  # print "in stub_configs2: #{YAML::dump(config)}\n"
35
45
  File.open(backup_config_file, "w") do |f|
36
46
  f.puts YAML.dump(config )
@@ -38,6 +48,9 @@ module Helpers
38
48
  end
39
49
 
40
50
  def import_gpg
51
+ # GPG v2.1+ dropped support for the --secret-keyring option (https://lists.gnupg.org/pipermail/gnupg-devel/2014-December/029296.html)
52
+ # This means that we need to import private keys too
53
+ system("gpg --import #{PRIVATE_KEY_PATH}") || raise("Could not import public key")
41
54
  system("gpg --import #{PUBLIC_KEY_PATH}") || raise("Could not import public key")
42
55
  end
43
56
 
@@ -55,7 +68,7 @@ module Helpers
55
68
  return File.read(PUBLIC_KEY_PATH), File.read(PRIVATE_KEY_PATH)
56
69
  end
57
70
 
58
- def run_after
71
+ def run_after(skip_file_remove = false)
59
72
  FileUtils.rm_f(backup_config_file)
60
73
  filenames = Dir.glob("#{tmp_dir}/*")
61
74
  if filenames.any?
@@ -63,16 +76,17 @@ module Helpers
63
76
  end
64
77
  end
65
78
 
66
- def teardown_dna(data)
67
- FileUtils.rm_f("#{tmp_dir}/dna.json")
79
+ def teardown_dna()
80
+ FileUtils.rm_f("#{tmp_dir}/chef/dna.json")
81
+ FileUtils.rm_r("#{tmp_dir}/chef")
68
82
  end
69
83
 
70
84
  def setup_dna(data)
71
- FileUtils.mkdir_p("#{tmp_dir}")
72
- if File.exist?("#{tmp_dir}/dna.json")
73
- FileUtils.rm("#{tmp_dir}/dna.json")
85
+ FileUtils.mkdir_p("#{tmp_dir}/chef")
86
+ if File.exist?("#{tmp_dir}/chef/dna.json")
87
+ FileUtils.rm("#{tmp_dir}/chef/dna.json")
74
88
  end
75
- File.open("#{tmp_dir}/dna.json", "w") do |f|
89
+ File.open("#{tmp_dir}/chef/dna.json", "w") do |f|
76
90
  f.puts data.to_json
77
91
  end
78
92
  end
@@ -80,7 +94,7 @@ module Helpers
80
94
  def backup_config_file
81
95
  "#{tmp_dir}/spec_backups.yml"
82
96
  end
83
-
97
+
84
98
  def mk_tmp
85
99
  FileUtils.mkdir_p("/tmp")
86
100
  end
@@ -102,7 +116,7 @@ module Helpers
102
116
  write_database_config('mysql', mysql_user, mysql_password, mysql_host, created_mysql_dbs.values, region)
103
117
  db_name
104
118
  end
105
-
119
+
106
120
  def drop_mysql_database(db_name)
107
121
  command = %Q{mysql -u#{mysql_user} -h#{mysql_host} #{mysql_password_option} -e "drop database if exists #{db_name};"}
108
122
  puts "*** MySQL Drop Command: #{command}"
@@ -184,6 +198,14 @@ module Helpers
184
198
  end
185
199
  end
186
200
 
201
+ def log_dir
202
+ if spec_config['log_dir'].nil?
203
+ File.dirname(__FILE__) + "/log/"
204
+ else
205
+ spec_config['log_dir'] || File.dirname("./log/")
206
+ end
207
+ end
208
+
187
209
  def mysql_user
188
210
  spec_config['mysql_user'] || "root"
189
211
  end
@@ -281,5 +303,9 @@ module Helpers
281
303
  EY::Backup.logger.stdout.string
282
304
  end
283
305
 
306
+ def stderr
307
+ EY::Backup.logger.stderr.string
308
+ end
309
+
284
310
  load_spec_config
285
311
  end
data/spec/spec_helper.rb CHANGED
@@ -1,5 +1,8 @@
1
1
  require File.dirname(__FILE__) + "/../lib/ey-flex"
2
2
 
3
+ require 'simplecov'
4
+ SimpleCov.start
5
+
3
6
  require 'fakeweb'
4
7
  require 'fakefs/safe'
5
8
  require 'randexp'