heroku-rds 0.4.0 → 0.5.0
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.
- data/.gemspec +1 -1
- data/README.md +10 -12
- data/lib/heroku/commands/rds.rb +89 -19
- metadata +3 -3
data/.gemspec
CHANGED
@@ -3,7 +3,7 @@ require 'rubygems' unless Object.const_defined?(:Gem)
|
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = "heroku-rds"
|
6
|
-
s.version = '0.
|
6
|
+
s.version = '0.5.0'
|
7
7
|
s.authors = ["Jonathan Dance"]
|
8
8
|
s.email = "rubygems@wuputah.com"
|
9
9
|
s.homepage = "http://github.com/wegowise/heroku-rds"
|
data/README.md
CHANGED
@@ -27,14 +27,17 @@ plugins:install`.
|
|
27
27
|
|
28
28
|
### Optional Packages
|
29
29
|
|
30
|
-
Commands involving data transfer support a progress bar using `pv`.
|
31
|
-
Install `pv` to see the awesome. Most package managers have a pv
|
32
|
-
package:
|
30
|
+
* Commands involving data transfer support a progress bar using `pv`.
|
31
|
+
Install `pv` to see the awesome. Most package managers have a pv
|
32
|
+
package:
|
33
33
|
|
34
34
|
brew install pv # OS X
|
35
35
|
apt-get install pv # linux/fink
|
36
36
|
port install pv # BSD/macports
|
37
37
|
|
38
|
+
* `rds:ingress` can use hirb to format tabular data. `gem install hirb`
|
39
|
+
to install it.
|
40
|
+
|
38
41
|
## Usage
|
39
42
|
|
40
43
|
Access the command list at any time by typing `heroku help rds`:
|
@@ -48,19 +51,14 @@ Access the command list at any time by typing `heroku help rds`:
|
|
48
51
|
|
49
52
|
rds:access # displays current ingress access settings
|
50
53
|
rds:dump [FILE] # Download a database dump, bzipped and saved locally
|
54
|
+
rds:import FILE # uploads a local database dump into the remote databse
|
51
55
|
rds:ingress [IP] [SECURITY GROUP] # Authorize ingress access to a particular IP
|
52
56
|
rds:pull [RAILS_ENV or DATABASE_URL] # downloads the remote database into a local database
|
57
|
+
rds:push [RAILS_ENV or DATABASE_URL] # uploads the local database into the remote database
|
53
58
|
rds:revoke [IP] [SECURITY GROUP] # Revokes previously-granted ingress access from a particular IP
|
54
59
|
|
55
60
|
## Planned features
|
56
61
|
|
57
|
-
### Short term
|
58
|
-
|
59
|
-
* rds:import - load a local database dump into the remote database
|
60
|
-
* rds:push - export a local database into the remote database
|
61
|
-
|
62
|
-
### Lower priority
|
63
|
-
|
64
62
|
* rds:snapshot - capture a snapshot
|
65
63
|
* rds:restore - restore from a snapshot
|
66
64
|
* rds:reboot - reboot instance
|
@@ -69,5 +67,5 @@ Access the command list at any time by typing `heroku help rds`:
|
|
69
67
|
|
70
68
|
These commands are not ingress related so the target of the command
|
71
69
|
cannot be inferred from DATABASE\_URL. This functionality is also
|
72
|
-
readily available from the RDS dashboard, so implementing them is not
|
73
|
-
|
70
|
+
readily available from the RDS dashboard, so implementing them is not
|
71
|
+
considered critical.
|
data/lib/heroku/commands/rds.rb
CHANGED
@@ -88,17 +88,24 @@ module Heroku::Command
|
|
88
88
|
# displays current ingress access settings
|
89
89
|
#
|
90
90
|
def access
|
91
|
-
data =
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
group.ip_ranges.map do |ip_range|
|
96
|
-
[group.id, ip_range['CIDRIP'], ip_range['Status']]
|
91
|
+
data = Array.new
|
92
|
+
rds.security_groups.all.each do |data, group|
|
93
|
+
group.ec2_security_groups.each do |group_access|
|
94
|
+
data << [group.id, group_access['EC2SecurityGroupName'] + ' @ ' + group_access['EC2SecurityGroupOwnerId'], group_access['Status']]
|
97
95
|
end
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
96
|
+
group.ip_ranges.each do |ip_range|
|
97
|
+
data << [group.id, ip_range['CIDRIP'], ip_range['Status']]
|
98
|
+
end
|
99
|
+
data
|
100
|
+
end
|
101
|
+
begin
|
102
|
+
require 'hirb'
|
103
|
+
puts Hirb::Helpers::AutoTable.render(data, :headers => ['Security Group', 'IP Range/Security Group', 'Status'])
|
104
|
+
rescue LoadError
|
105
|
+
data.unshift ['SECURITY GROUP', 'IP RANGE / SECURITY GROUP', 'STATUS']
|
106
|
+
lengths = (0..2).map { |i| data.map { |d| d[i].length }.max }
|
107
|
+
puts data.map { |d| '%-*s %-*s %-*s' % [lengths[0], d[0], lengths[1], d[1], lengths[2], d[2]] }.join("\n")
|
108
|
+
end
|
102
109
|
end
|
103
110
|
|
104
111
|
# rds:pull [RAILS_ENV or DATABASE_URL]
|
@@ -110,8 +117,69 @@ module Heroku::Command
|
|
110
117
|
# the transfer.
|
111
118
|
#
|
112
119
|
def pull
|
113
|
-
check_dependencies('mysqldump', 'mysql')
|
120
|
+
check_dependencies('mysqldump', 'mysql', '/bin/sh')
|
121
|
+
target = parse_db_location(args.shift || 'development')
|
122
|
+
|
123
|
+
display "This will erase all data in the #{target['database'].inspect} database" +
|
124
|
+
(target['host'].empty? ? '' : " on #{target['host']}") + "!"
|
125
|
+
exit unless dangerous_prompt
|
126
|
+
|
127
|
+
copy_db_to_db(database_uri, target)
|
128
|
+
end
|
129
|
+
|
130
|
+
# rds:push [RAILS_ENV or DATABASE_URL]
|
131
|
+
#
|
132
|
+
# uploads the local database into the remote database
|
133
|
+
#
|
134
|
+
# If a RAILS_ENV or DATABASE_URL is not specified, the current development environment
|
135
|
+
# is used (as read from config/database.yml). This command will confirm before executing
|
136
|
+
# the transfer.
|
137
|
+
#
|
138
|
+
def push
|
139
|
+
check_dependencies('mysqldump', 'mysql', '/bin/sh')
|
140
|
+
source = parse_db_location(args.shift || 'development')
|
141
|
+
|
142
|
+
display "This will replace the #{app} database with the #{source['database'].inspect} database" +
|
143
|
+
(source['host'].empty? ? '' : " on #{source['host']}") + "!"
|
144
|
+
exit unless dangerous_prompt
|
145
|
+
|
146
|
+
copy_db_to_db(source, database_uri)
|
147
|
+
end
|
148
|
+
|
149
|
+
# rds:import FILE
|
150
|
+
#
|
151
|
+
# uploads a local database dump into the remote databse
|
152
|
+
#
|
153
|
+
# supports gzipped, bzipped, and uncompressed sql dumps
|
154
|
+
#
|
155
|
+
def import
|
156
|
+
check_dependencies('mysql', '/bin/sh')
|
157
|
+
source = args.shift or raise CommandFailed, "You must specify a file to import from"
|
158
|
+
File.readable?(source) or raise CommandFailed, "#{source.inspect} is not readable"
|
159
|
+
command = case source
|
160
|
+
when /\.bz2$/
|
161
|
+
check_dependencies('bzcat')
|
162
|
+
'bzcat'
|
163
|
+
when /\.gz$/
|
164
|
+
check_dependencies('gunzip')
|
165
|
+
'gunzip -c'
|
166
|
+
else
|
167
|
+
check_dependencies('cat')
|
168
|
+
'cat'
|
169
|
+
end
|
170
|
+
|
171
|
+
display "This will replace the #{app} database with #{source}!"
|
172
|
+
exit unless dangerous_prompt
|
173
|
+
|
174
|
+
exec('/bin/sh', '-c',
|
175
|
+
"#{command} #{args_to_s(source)}" +
|
176
|
+
pv_pipe +
|
177
|
+
%{| mysql --compress } + args_to_s(mysql_args(database_uri)))
|
178
|
+
end
|
114
179
|
|
180
|
+
private
|
181
|
+
|
182
|
+
def parse_db_location(target)
|
115
183
|
target = args.shift || 'development'
|
116
184
|
if target =~ %r{://}
|
117
185
|
target = uri_to_hash(validate_db(URI.parse(target)))
|
@@ -122,19 +190,20 @@ module Heroku::Command
|
|
122
190
|
db_config.has_key?(target)
|
123
191
|
target = validate_db(db_config[target], target)
|
124
192
|
end
|
193
|
+
target
|
194
|
+
end
|
125
195
|
|
126
|
-
|
127
|
-
|
128
|
-
|
196
|
+
def dangerous_prompt
|
197
|
+
ask("Are you sure you wish to continue? [yN] ").downcase == 'y'
|
198
|
+
end
|
129
199
|
|
200
|
+
def copy_db_to_db(src, dest)
|
130
201
|
exec('/bin/sh', '-c',
|
131
|
-
'mysqldump --compress --single-transaction ' + args_to_s(mysql_args(
|
202
|
+
'mysqldump --compress --single-transaction ' + args_to_s(mysql_args(src)) + ' ' +
|
132
203
|
pv_pipe +
|
133
|
-
%{| mysql --compress } + args_to_s(mysql_args(
|
204
|
+
%{| mysql --compress } + args_to_s(mysql_args(dest)))
|
134
205
|
end
|
135
206
|
|
136
|
-
private
|
137
|
-
|
138
207
|
def current_ip
|
139
208
|
# simple rack app which returns your external IP
|
140
209
|
RestClient::Resource.new("http://ip4.heroku.com")['/'].get.strip
|
@@ -160,7 +229,8 @@ module Heroku::Command
|
|
160
229
|
args
|
161
230
|
end
|
162
231
|
|
163
|
-
def args_to_s(args)
|
232
|
+
def args_to_s(*args)
|
233
|
+
args = args.flatten
|
164
234
|
"'" + args.collect { |s| s.gsub("'", "\\'") }.join("' '") + "'"
|
165
235
|
end
|
166
236
|
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: heroku-rds
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.
|
5
|
+
version: 0.5.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Jonathan Dance
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-06-
|
13
|
+
date: 2011-06-03 00:00:00 -04:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -45,8 +45,8 @@ extra_rdoc_files:
|
|
45
45
|
- README.md
|
46
46
|
- LICENSE.txt
|
47
47
|
files:
|
48
|
-
- lib/heroku/commands/rds.rb
|
49
48
|
- lib/heroku/rds.rb
|
49
|
+
- lib/heroku/commands/rds.rb
|
50
50
|
- README.md
|
51
51
|
- .gemspec
|
52
52
|
- init.rb
|