ey_cloud_server 1.4.54 → 1.4.58

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZTdlYWY2NzRmNzI0YjA2ODVlNzBhYWM5ZTQyZTIzODJjMjEyMmJjYw==
4
+ ZTRlYTdlMDYxN2UzYzI2MTNjM2Y1NGMzMmFjNmJkMWQzOTVkYWU4Mg==
5
5
  data.tar.gz: !binary |-
6
- ZDkxZjUxMjA5Njc3MTI3NmViNmEwYmJhMDZlZjgwNTMyNTBkNWIzOQ==
6
+ MGQ4M2EwYWVhMmY2OGU0ZGUxYmNhNDdkODdiMjBmN2MwNjdlZDRkZA==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- YmQ1MDQwODBkMWNlYTFkMmI5NzM0YzdhM2UyYzVkNDQyZmNlODJjOTdkNDc0
10
- YWM3ZjliNjFiZDhhMjc2MmFlZTRjMzU5MjUzY2FhNzQ0ZjkyYTUyZDQzMzM2
11
- YTQwZjI3MzZmYTZhNTNlYTgzZDg2ZDFiNWNkMzg5ZDZlZDBjMzc=
9
+ N2M0ZGUzOWJhNDRlYTNiMzIxYzQ4YzcwZDY1MGI0OTY2NTVkZDQxZTA4YmQ2
10
+ OGY5NmUwNTg4ZDFiM2ZjMjNlNmExMjBmMWJhNjFhNGUxYTVlYzhmODlhYjc0
11
+ M2E2N2M5MWJjZDRlZWE3MGM2MDdkNGJlNDkzMjA2MGIxMDBkZjM=
12
12
  data.tar.gz: !binary |-
13
- MDQwZWY0MzgzMGI4NTI2MTgyMGQ0ZWQ5MzRlM2EzOTI5ZWFlY2EzMzAxMmRi
14
- MTAwNDI3YzI0ODU4YmY3YzliZTcxNmFlNmNjMWM0Y2I3YzYzMDNkODdmODEx
15
- ZWM4YTk3NTM3NTM1MGMwZjcxYTc1ODYyM2Q5ZWY5YTRkZTg0YTQ=
13
+ Mzc1YTczYzU1M2QyODA2NDgwZjE0MzJmNTVmOGEzOGZlNzJjYTc5NGRmYmEz
14
+ OWZjNjc0NjEyYWVhM2JkOGQxMmFkZTE0NWViNWQ2MDBlYzVjZGVmZTZkZTc2
15
+ NzgwYTI2NjcwZmQ0NWUwOWVmOTlkNTM3NjM2MzMxYjBlMGE4OTI=
@@ -0,0 +1,182 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+ require 'yaml'
5
+ require 'tempfile'
6
+ require 'timeout'
7
+
8
+ def opt_parse(argv)
9
+ options = {}
10
+ optparse = OptionParser.new do |opts|
11
+ opts.banner = "Usage: #{__FILE__} --env <environment name> --database <database_name> --action <action> [options]"
12
+ opts.separator ''
13
+ opts.separator "Wrapper for eybackup used for listing, downloading and restoring database backups. The main purpose for this tool is to"
14
+ opts.separator "simplify the process of accessing backups from one environment in a different environment (e.g. access Production backups"
15
+ opts.separator "from Staging). This can also be used for restoring backups within the current environment."
16
+ opts.separator ''
17
+ opts.on('-h', '--help', 'Displays this Help message') { puts opts; exit}
18
+
19
+ opts.separator ''
20
+ opts.separator 'Common Options:'
21
+
22
+ opts.on('-e', '--env environment_name', "Specifies the source environment name for the backups you will be working with.") { |env| options[:env] = env }
23
+ opts.on('-d', '--database database_name', "Name of the source database to get backups for.") { |dbname| options[:databases] = [dbname] }
24
+ actions=['list', 'restore', 'download']
25
+ opts.on('-a', '--action action_name', "The action you want to perform using the backup #{actions}.") do |action|
26
+ unless actions.include?(action)
27
+ puts "Invalid action: '#{action}' must be one of #{actions}\n\n"
28
+ puts opts
29
+ exit 1
30
+ end
31
+ options[:action] = action
32
+ end
33
+ opts.on('-i', '--index BACKUP_INDEX', 'Download/Restore the backup specified by index','BACKUP_INDEX uses the format #{index_number}:#{db_name}',
34
+ "The string 'last' will automatically reference the most recent available backup.") do |index|
35
+ options[:index] = index
36
+ end
37
+ opts.on('-f', '--force', 'Force mode, skips all confirmation prompts for use with automated restores.') { options[:force] = true }
38
+
39
+ opts.separator ''
40
+ opts.separator 'Additional Options:'
41
+
42
+ opts.on('-u', '--aws_secret_id key', 'AWS S3 Key') { |key| options[:aws_key_id] = key }
43
+ opts.on('-p', '--aws_secret_key secret', 'AWS S3 Secret Key') { |secret| options[:aws_secret_key] = secret }
44
+ opts.on('-b', '--backup_bucket bucket', 'AWS S3 bucket identifier') { |bucket| options[:backup_bucket] = bucket }
45
+ opts.on('-v', '--verbose', "Enable debug info for this wrapper.") { $verbose = true }
46
+ opts.on('-c', '--config', "Alternate config file for eyrestore (default ~/.eyrestore.confg.yml)") do |path|
47
+ unless File.exists?(path)
48
+ puts "Invalid config file path '#{path}', no file at that location."
49
+ exit 1
50
+ end
51
+ options[:def_config] = path
52
+ end
53
+ opts.separator ''
54
+ opts.separator 'Examples:'
55
+ opts.separator '* List backups from an environment named production for a database named todo'
56
+ opts.separator " sudo -i #{__FILE__} --env production --database todo --action list"
57
+ opts.separator ''
58
+ opts.separator '* Download the most recent backup from an environment named production for a database named todo'
59
+ opts.separator " sudo -i #{__FILE__} --env production --database todo --action download --index last"
60
+ opts.separator ''
61
+ opts.separator "* Download a backup from an environment named production for a database named todo, prompt with a list of available backups"
62
+ opts.separator " sudo -i #{__FILE__} --env production --database todo --action download"
63
+ opts.separator ''
64
+ opts.separator '* Restore the most recent backup from an environment named production for a database named todo'
65
+ opts.separator " sudo -i #{__FILE__} --env production --database todo --action restore --index last"
66
+ opts.separator ''
67
+ end
68
+ optparse.parse!
69
+ options
70
+ end
71
+
72
+ def debug(msg)
73
+ puts '[' + Time.now.strftime("%D %T") + ']: DEBUG: ' + msg if $verbose
74
+ end
75
+
76
+ def find_engine
77
+ debug("Searching for database engine based on file '/etc/.*.backups.yml'")
78
+ main_config = Dir['/etc/.*.backups.yml'].first
79
+ abort "Failed to find eybackup config at '/etc/.*.backups.yml', this needs to run on a database instance." unless main_config
80
+ debug("Found file '#{main_config}'")
81
+ File.basename(main_config).split('.')[1]
82
+ end
83
+
84
+ def extra_validations(options)
85
+ mandatory = [:databases, :env, :action]
86
+ missing = mandatory.select{ |param| options[param].nil? }
87
+ raise OptionParser::MissingArgument, missing.join(',') unless missing.empty?
88
+ end
89
+
90
+ def list_backups(engine, db, path)
91
+ command = "eybackup -e #{engine} -l #{db} -c #{path}"
92
+ debug("Listing backups with command: #{command}")
93
+ res = %x{#{command}}
94
+ last = res.chomp.split("\n").last
95
+ abort "No Backups Found for that environment and database." if last.match(/0 backup\(s\) found/)
96
+ res
97
+ end
98
+
99
+ def gets_timeout( prompt, secs )
100
+ print prompt + "[timeout=#{secs}secs]: "
101
+ Timeout::timeout( secs ) { gets.chomp }
102
+ rescue Timeout::Error
103
+ puts "*timeout"
104
+ '' # return nil if timeout
105
+ end
106
+
107
+ def last_backup_idx(listing)
108
+ last = listing.chomp.split("\n").last
109
+ if last.split.first.match(/\d+:\w+/)
110
+ index = last.split.first
111
+ else
112
+ index = last.split[3]
113
+ end
114
+ end
115
+
116
+ options = opt_parse(ARGV)
117
+ options[:def_config] = '~/.eyrestore.config.yml' unless options[:def_config]
118
+
119
+ # auto-detect the type of database running in the given environment
120
+ engine = find_engine
121
+
122
+ # parse eybackup config file
123
+ config = YAML.load_file("/etc/.#{engine}.backups.yml")
124
+ this_env = config[:env]
125
+ # delete these just in case
126
+ config.delete(:env)
127
+ config.delete(:databases)
128
+
129
+ # override config from eyrestore config file
130
+ eyrestore = YAML.load_file(options[:def_config]) if File.exists?(options[:def_config])
131
+ config.merge!(eyrestore) unless eyrestore.nil?
132
+
133
+ # override config from command line options
134
+ config.merge!(options)
135
+ extra_validations(config)
136
+ debug("Config Options: '#{config}'")
137
+
138
+ # create a temporary configuration file from ~/.eyrestore.config.yml
139
+ temp_config = Tempfile.new("eyrestore")
140
+ temp_config.write(config.to_yaml)
141
+ temp_config.rewind
142
+ debug("Generated temporary config file: '#{temp_config.path}'")
143
+
144
+ db = config[:databases].first
145
+ temp = temp_config.path
146
+ if config[:action] == 'list' or ! config[:index]
147
+ puts list_backups(engine, db, temp)
148
+ end
149
+
150
+ # confirm environment overwrite if restoring
151
+ if config[:action] == 'restore' and ! config[:force]
152
+ response = gets_timeout("You are restoring the backup for '#{db}' from '#{config[:env]}' into '#{this_env}', THIS MAY BE DESTRUCTIVE; are you sure you want to proceed (Y/n) ? ", 30)
153
+ exit unless response.downcase == 'y'
154
+ end
155
+
156
+
157
+ if ['download','restore'].include?(config[:action])
158
+ config[:index] = gets_timeout("Enter the backup index to use for #{config[:action]} (e.g. 9:#{db}) ", 30) unless config[:index]
159
+ config[:index] = last_backup_idx(list_backups(engine, db, temp)) if config[:index] == 'last'
160
+ abort "Invalid backup index '#{config[:index]}'." unless config[:index].match(/^\d+:\w+$/)
161
+
162
+ action = config[:action] == 'restore' ? '-r' : '-d'
163
+ debug("Set action flag for eybackup to '#{action}' based on action of '#{config[:action]}'")
164
+
165
+ # test eybackup version for force option
166
+ ey_cloud_server_version = Gem::Version.new(%x{/usr/local/ey_resin/ruby/bin/gem list ey_cloud_server}.split[1].gsub('(','').gsub(')','').gsub(',',''))
167
+ force = ey_cloud_server_version >= Gem::Version.new('1.4.51') ? '--force' : ''
168
+ debug("eybackup version '#{ey_cloud_server_version}' so force is set to '#{force}'")
169
+
170
+ command="eybackup -e #{engine} -c #{temp} #{action} #{config[:index]} #{force}"
171
+
172
+ puts "Running '#{config[:action]}' on index '#{config[:index]}'."
173
+ debug("Running command: #{command}")
174
+
175
+ res=%x{#{command}}
176
+ puts res
177
+ puts "Restore complete!" if res.split("\n").last.match(/^Filename/) and config[:action] == 'restore'
178
+ end
179
+
180
+ # cleanup temporary config file
181
+ temp_config.close
182
+ temp_config.unlink
@@ -1,5 +1,5 @@
1
1
  module EY
2
2
  module CloudServer
3
- VERSION = '1.4.54'
3
+ VERSION = '1.4.58'
4
4
  end
5
5
  end
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.54
4
+ version: 1.4.58
5
5
  platform: ruby
6
6
  authors:
7
7
  - EngineYard
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-01-25 00:00:00.000000000 Z
11
+ date: 2017-02-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -238,6 +238,7 @@ email:
238
238
  executables:
239
239
  - ey-snapshots
240
240
  - eybackup
241
+ - eyrestore
241
242
  extensions: []
242
243
  extra_rdoc_files: []
243
244
  files:
@@ -247,6 +248,7 @@ files:
247
248
  - TODO
248
249
  - bin/ey-snapshots
249
250
  - bin/eybackup
251
+ - bin/eyrestore
250
252
  - features/downloading_a_mysql_backup.feature
251
253
  - features/making_a_postgresql_backup.feature
252
254
  - features/restoring_postgres_backup.feature
@@ -312,7 +314,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
312
314
  version: '0'
313
315
  requirements: []
314
316
  rubyforge_project:
315
- rubygems_version: 2.6.8
317
+ rubygems_version: 2.4.5
316
318
  signing_key:
317
319
  specification_version: 4
318
320
  summary: Server side components for Engine Yard's cloud