ey_cloud_server 1.4.54 → 1.4.58

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 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