rubber 2.3.1 → 2.4.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.
- checksums.yaml +4 -4
- data/CHANGELOG +15 -0
- data/lib/rubber/cloud.rb +1 -1
- data/lib/rubber/cloud/aws.rb +376 -10
- data/lib/rubber/cloud/base.rb +152 -0
- data/lib/rubber/cloud/digital_ocean.rb +96 -0
- data/lib/rubber/cloud/fog.rb +8 -200
- data/lib/rubber/cloud/generic.rb +68 -0
- data/lib/rubber/instance.rb +6 -1
- data/lib/rubber/recipes/rubber/deploy.rb +16 -14
- data/lib/rubber/recipes/rubber/instances.rb +21 -14
- data/lib/rubber/recipes/rubber/security_groups.rb +4 -187
- data/lib/rubber/recipes/rubber/setup.rb +25 -1
- data/lib/rubber/recipes/rubber/utils.rb +7 -4
- data/lib/rubber/util.rb +4 -0
- data/lib/rubber/version.rb +1 -1
- data/templates/base/config/deploy.rb +11 -5
- data/templates/base/config/rubber/rubber.yml +15 -2
- data/templates/postgresql/config/rubber/role/postgresql/pg_hba.conf +4 -2
- data/test/cloud/aws_test.rb +1 -1
- data/test/cloud/digital_ocean_test.rb +70 -0
- data/test/cloud/fog_test.rb +4 -2
- data/test/fixtures/basic/test.pem.pub +1 -0
- data/test/util_test.rb +8 -0
- metadata +7 -3
@@ -263,16 +263,17 @@ namespace :rubber do
|
|
263
263
|
role_names = instance_roles.collect{|x| x.name}
|
264
264
|
env = rubber_cfg.environment.bind(role_names, instance_alias)
|
265
265
|
|
266
|
-
# We need to use security_groups during create, so create them up front
|
267
266
|
mutex.synchronize do
|
268
|
-
|
267
|
+
cloud.before_create_instance(instance_alias, role_names)
|
269
268
|
end
|
269
|
+
|
270
270
|
security_groups = get_assigned_security_groups(instance_alias, role_names)
|
271
271
|
|
272
272
|
cloud_env = env.cloud_providers[env.cloud_provider]
|
273
273
|
ami = cloud_env.image_id
|
274
274
|
ami_type = cloud_env.image_type
|
275
|
-
availability_zone =
|
275
|
+
availability_zone = cloud_env.availability_zone
|
276
|
+
region = cloud_env.region
|
276
277
|
|
277
278
|
create_spot_instance ||= cloud_env.spot_instance
|
278
279
|
|
@@ -306,8 +307,8 @@ namespace :rubber do
|
|
306
307
|
end
|
307
308
|
|
308
309
|
if !create_spot_instance || (create_spot_instance && max_wait_time < 0)
|
309
|
-
logger.info "Creating instance #{ami}/#{ami_type}/#{security_groups.join(',') rescue 'Default'}/#{availability_zone || 'Default'}"
|
310
|
-
instance_id = cloud.create_instance(ami, ami_type, security_groups, availability_zone)
|
310
|
+
logger.info "Creating instance #{ami}/#{ami_type}/#{security_groups.join(',') rescue 'Default'}/#{availability_zone || region || 'Default'}"
|
311
|
+
instance_id = cloud.create_instance(instance_alias, ami, ami_type, security_groups, availability_zone, region)
|
311
312
|
end
|
312
313
|
|
313
314
|
logger.info "Instance #{instance_alias} created: #{instance_id}"
|
@@ -317,10 +318,8 @@ namespace :rubber do
|
|
317
318
|
rubber_instances.add(instance_item)
|
318
319
|
rubber_instances.save()
|
319
320
|
|
320
|
-
|
321
|
-
|
322
|
-
Rubber::Util.retry_on_failure(Exception, :retry_sleep => 0.5, :retry_count => 100) do
|
323
|
-
Rubber::Tag::update_instance_tags(instance_alias)
|
321
|
+
mutex.synchronize do
|
322
|
+
cloud.after_create_instance(instance_item)
|
324
323
|
end
|
325
324
|
end
|
326
325
|
|
@@ -349,9 +348,13 @@ namespace :rubber do
|
|
349
348
|
|
350
349
|
env = rubber_cfg.environment.bind(instance_item.role_names, instance_alias)
|
351
350
|
|
352
|
-
instance = cloud.describe_instances(instance_item.instance_id).first
|
351
|
+
instance = cloud.describe_instances(instance_item.instance_id).first
|
352
|
+
|
353
|
+
mutex.synchronize do
|
354
|
+
cloud.before_refresh_instance(instance_item)
|
355
|
+
end
|
353
356
|
|
354
|
-
if instance[:state] ==
|
357
|
+
if instance[:state] == cloud.active_state
|
355
358
|
print "\n"
|
356
359
|
logger.info "Instance running, fetching hostname/ip data"
|
357
360
|
instance_item.external_host = instance[:external_host]
|
@@ -359,6 +362,7 @@ namespace :rubber do
|
|
359
362
|
instance_item.internal_host = instance[:internal_host]
|
360
363
|
instance_item.internal_ip = instance[:internal_ip]
|
361
364
|
instance_item.zone = instance[:zone]
|
365
|
+
instance_item.provider = instance[:provider]
|
362
366
|
instance_item.platform = instance[:platform]
|
363
367
|
instance_item.root_device_type = instance[:root_device_type]
|
364
368
|
rubber_instances.save()
|
@@ -367,6 +371,8 @@ namespace :rubber do
|
|
367
371
|
# weird cap/netssh bug, sometimes just hangs forever on initial connect, so force a timeout
|
368
372
|
begin
|
369
373
|
Timeout::timeout(30) do
|
374
|
+
puts 'Trying to enable root login'
|
375
|
+
|
370
376
|
# turn back on root ssh access if we are using root as the capistrano user for connecting
|
371
377
|
enable_root_ssh(instance_item.external_ip, fetch(:initial_ssh_user, 'ubuntu')) if user == 'root'
|
372
378
|
# force a connection so if above isn't enabled we still timeout if initial connection hangs
|
@@ -380,6 +386,10 @@ namespace :rubber do
|
|
380
386
|
end
|
381
387
|
end
|
382
388
|
|
389
|
+
mutex.synchronize do
|
390
|
+
cloud.after_refresh_instance(instance_item)
|
391
|
+
end
|
392
|
+
|
383
393
|
return true
|
384
394
|
end
|
385
395
|
return false
|
@@ -387,9 +397,6 @@ namespace :rubber do
|
|
387
397
|
|
388
398
|
def post_refresh
|
389
399
|
env = rubber_cfg.environment.bind(nil, nil)
|
390
|
-
|
391
|
-
# update the remote name/environment tags
|
392
|
-
update_tags
|
393
400
|
|
394
401
|
# setup amazon elastic ips if configured to do so
|
395
402
|
setup_static_ips
|
@@ -6,7 +6,9 @@ namespace :rubber do
|
|
6
6
|
Likewise, rules within a group will get created, and those not will be removed
|
7
7
|
DESC
|
8
8
|
required_task :setup_security_groups do
|
9
|
-
|
9
|
+
servers = find_servers_for_task(current_task)
|
10
|
+
|
11
|
+
cloud.setup_security_groups(servers.collect(&:host))
|
10
12
|
end
|
11
13
|
|
12
14
|
desc <<-DESC
|
@@ -37,192 +39,7 @@ namespace :rubber do
|
|
37
39
|
security_groups += roles
|
38
40
|
end
|
39
41
|
security_groups = security_groups.uniq.compact.reject {|x| x.empty? }
|
40
|
-
security_groups = security_groups.collect {|x| isolate_group_name(x) }
|
42
|
+
security_groups = security_groups.collect {|x| cloud.isolate_group_name(x) }
|
41
43
|
return security_groups
|
42
44
|
end
|
43
|
-
|
44
|
-
def setup_security_groups(host=nil, roles=[])
|
45
|
-
env = rubber_cfg.environment.bind(roles, host)
|
46
|
-
security_group_defns = Hash[env.security_groups.to_a]
|
47
|
-
if env.auto_security_groups
|
48
|
-
sghosts = (rubber_instances.collect{|ic| ic.name } + [host]).uniq.compact
|
49
|
-
sgroles = (rubber_instances.all_roles + roles).uniq.compact
|
50
|
-
security_group_defns = inject_auto_security_groups(security_group_defns, sghosts, sgroles)
|
51
|
-
sync_security_groups(security_group_defns)
|
52
|
-
else
|
53
|
-
sync_security_groups(security_group_defns)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
def inject_auto_security_groups(groups, hosts, roles)
|
58
|
-
hosts.each do |name|
|
59
|
-
group_name = name
|
60
|
-
groups[group_name] ||= {'description' => "Rubber automatic security group for host: #{name}", 'rules' => []}
|
61
|
-
end
|
62
|
-
roles.each do |name|
|
63
|
-
group_name = name
|
64
|
-
groups[group_name] ||= {'description' => "Rubber automatic security group for role: #{name}", 'rules' => []}
|
65
|
-
end
|
66
|
-
return groups
|
67
|
-
end
|
68
|
-
|
69
|
-
def isolate_prefix
|
70
|
-
return "#{rubber_env.app_name}_#{Rubber.env}_"
|
71
|
-
end
|
72
|
-
|
73
|
-
def isolate_group_name(group_name)
|
74
|
-
if rubber_env.isolate_security_groups
|
75
|
-
group_name =~ /^#{isolate_prefix}/ ? group_name : "#{isolate_prefix}#{group_name}"
|
76
|
-
else
|
77
|
-
group_name
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
def isolate_groups(groups)
|
82
|
-
renamed = {}
|
83
|
-
groups.each do |name, group|
|
84
|
-
new_name = isolate_group_name(name)
|
85
|
-
new_group = Marshal.load(Marshal.dump(group))
|
86
|
-
new_group['rules'].each do |rule|
|
87
|
-
old_ref_name = rule['source_group_name']
|
88
|
-
if old_ref_name
|
89
|
-
# don't mangle names if the user specifies this is an external group they are giving access to.
|
90
|
-
# remove the external_group key to allow this to match with groups retrieved from cloud
|
91
|
-
is_external = rule.delete('external_group')
|
92
|
-
if ! is_external && old_ref_name !~ /^#{isolate_prefix}/
|
93
|
-
rule['source_group_name'] = isolate_group_name(old_ref_name)
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
97
|
-
renamed[new_name] = new_group
|
98
|
-
end
|
99
|
-
return renamed
|
100
|
-
end
|
101
|
-
|
102
|
-
def sync_security_groups(groups)
|
103
|
-
return unless groups
|
104
|
-
|
105
|
-
groups = Rubber::Util::stringify(groups)
|
106
|
-
groups = isolate_groups(groups)
|
107
|
-
group_keys = groups.keys.clone()
|
108
|
-
|
109
|
-
# For each group that does already exist in cloud
|
110
|
-
cloud_groups = cloud.describe_security_groups()
|
111
|
-
cloud_groups.each do |cloud_group|
|
112
|
-
group_name = cloud_group[:name]
|
113
|
-
|
114
|
-
# skip those groups that don't belong to this project/env
|
115
|
-
next if rubber_env.isolate_security_groups && group_name !~ /^#{isolate_prefix}/
|
116
|
-
|
117
|
-
if group_keys.delete(group_name)
|
118
|
-
# sync rules
|
119
|
-
logger.debug "Security Group already in cloud, syncing rules: #{group_name}"
|
120
|
-
group = groups[group_name]
|
121
|
-
|
122
|
-
# convert the special case default rule into what it actually looks like when
|
123
|
-
# we query ec2 so that we can match things up when syncing
|
124
|
-
rules = group['rules'].clone
|
125
|
-
group['rules'].each do |rule|
|
126
|
-
if [2, 3].include?(rule.size) && rule['source_group_name'] && rule['source_group_account']
|
127
|
-
rules << rule.merge({'protocol' => 'tcp', 'from_port' => '1', 'to_port' => '65535' })
|
128
|
-
rules << rule.merge({'protocol' => 'udp', 'from_port' => '1', 'to_port' => '65535' })
|
129
|
-
rules << rule.merge({'protocol' => 'icmp', 'from_port' => '-1', 'to_port' => '-1' })
|
130
|
-
rules.delete(rule)
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
rule_maps = []
|
135
|
-
|
136
|
-
# first collect the rule maps from the request (group/user pairs are duplicated for tcp/udp/icmp,
|
137
|
-
# so we need to do this up frnot and remove duplicates before checking against the local rubber rules)
|
138
|
-
cloud_group[:permissions].each do |rule|
|
139
|
-
source_groups = rule.delete(:source_groups)
|
140
|
-
if source_groups
|
141
|
-
source_groups.each do |source_group|
|
142
|
-
rule_map = rule.clone
|
143
|
-
rule_map.delete(:source_ips)
|
144
|
-
rule_map[:source_group_name] = source_group[:name]
|
145
|
-
rule_map[:source_group_account] = source_group[:account]
|
146
|
-
rule_map = Rubber::Util::stringify(rule_map)
|
147
|
-
rule_maps << rule_map unless rule_maps.include?(rule_map)
|
148
|
-
end
|
149
|
-
else
|
150
|
-
rule_map = Rubber::Util::stringify(rule)
|
151
|
-
rule_maps << rule_map unless rule_maps.include?(rule_map)
|
152
|
-
end
|
153
|
-
end if cloud_group[:permissions]
|
154
|
-
# For each rule, if it exists, do nothing, otherwise remove it as its no longer defined locally
|
155
|
-
rule_maps.each do |rule_map|
|
156
|
-
if rules.delete(rule_map)
|
157
|
-
# rules match, don't need to do anything
|
158
|
-
# logger.debug "Rule in sync: #{rule_map.inspect}"
|
159
|
-
else
|
160
|
-
# rules don't match, remove them from cloud and re-add below
|
161
|
-
answer = nil
|
162
|
-
msg = "Rule '#{rule_map.inspect}' exists in cloud, but not locally"
|
163
|
-
if rubber_env.prompt_for_security_group_sync
|
164
|
-
answer = Capistrano::CLI.ui.ask("#{msg}, remove from cloud? [y/N]: ")
|
165
|
-
else
|
166
|
-
logger.info(msg)
|
167
|
-
end
|
168
|
-
|
169
|
-
if answer =~ /^y/
|
170
|
-
rule_map = Rubber::Util::symbolize_keys(rule_map)
|
171
|
-
if rule_map[:source_group_name]
|
172
|
-
cloud.remove_security_group_rule(group_name, rule_map[:protocol], rule_map[:from_port], rule_map[:to_port], {:name => rule_map[:source_group_name], :account => rule_map[:source_group_account]})
|
173
|
-
else
|
174
|
-
rule_map[:source_ips].each do |source_ip|
|
175
|
-
cloud.remove_security_group_rule(group_name, rule_map[:protocol], rule_map[:from_port], rule_map[:to_port], source_ip)
|
176
|
-
end if rule_map[:source_ips]
|
177
|
-
end
|
178
|
-
end
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
|
-
rules.each do |rule_map|
|
183
|
-
# create non-existing rules
|
184
|
-
logger.debug "Missing rule, creating: #{rule_map.inspect}"
|
185
|
-
rule_map = Rubber::Util::symbolize_keys(rule_map)
|
186
|
-
if rule_map[:source_group_name]
|
187
|
-
cloud.add_security_group_rule(group_name, rule_map[:protocol], rule_map[:from_port], rule_map[:to_port], {:name => rule_map[:source_group_name], :account => rule_map[:source_group_account]})
|
188
|
-
else
|
189
|
-
rule_map[:source_ips].each do |source_ip|
|
190
|
-
cloud.add_security_group_rule(group_name, rule_map[:protocol], rule_map[:from_port], rule_map[:to_port], source_ip)
|
191
|
-
end if rule_map[:source_ips]
|
192
|
-
end
|
193
|
-
end
|
194
|
-
else
|
195
|
-
# delete group
|
196
|
-
answer = nil
|
197
|
-
msg = "Security group '#{group_name}' exists in cloud but not locally"
|
198
|
-
if rubber_env.prompt_for_security_group_sync
|
199
|
-
answer = Capistrano::CLI.ui.ask("#{msg}, remove from cloud? [y/N]: ")
|
200
|
-
else
|
201
|
-
logger.debug(msg)
|
202
|
-
end
|
203
|
-
cloud.destroy_security_group(group_name) if answer =~ /^y/
|
204
|
-
end
|
205
|
-
end
|
206
|
-
|
207
|
-
# For each group that didnt already exist in cloud
|
208
|
-
group_keys.each do |group_name|
|
209
|
-
group = groups[group_name]
|
210
|
-
logger.debug "Creating new security group: #{group_name}"
|
211
|
-
# create each group
|
212
|
-
cloud.create_security_group(group_name, group['description'])
|
213
|
-
# create rules for group
|
214
|
-
group['rules'].each do |rule_map|
|
215
|
-
logger.debug "Creating new rule: #{rule_map.inspect}"
|
216
|
-
rule_map = Rubber::Util::symbolize_keys(rule_map)
|
217
|
-
if rule_map[:source_group_name]
|
218
|
-
cloud.add_security_group_rule(group_name, rule_map[:protocol], rule_map[:from_port], rule_map[:to_port], {:name => rule_map[:source_group_name], :account => rule_map[:source_group_account]})
|
219
|
-
else
|
220
|
-
rule_map[:source_ips].each do |source_ip|
|
221
|
-
cloud.add_security_group_rule(group_name, rule_map[:protocol], rule_map[:from_port], rule_map[:to_port], source_ip)
|
222
|
-
end if rule_map[:source_ips]
|
223
|
-
end
|
224
|
-
end
|
225
|
-
end
|
226
|
-
end
|
227
|
-
|
228
45
|
end
|
@@ -9,6 +9,7 @@ namespace :rubber do
|
|
9
9
|
link_bash
|
10
10
|
set_timezone
|
11
11
|
enable_multiverse
|
12
|
+
install_core_packages
|
12
13
|
upgrade_packages
|
13
14
|
install_packages
|
14
15
|
setup_volumes
|
@@ -19,9 +20,16 @@ namespace :rubber do
|
|
19
20
|
|
20
21
|
# Sets up instance to allow root access (e.g. recent canonical AMIs)
|
21
22
|
def enable_root_ssh(ip, initial_ssh_user)
|
23
|
+
# Capistrano uses the :password variable for sudo commands. Since this setting is generally used for the deploy user,
|
24
|
+
# but we need it this one time for the initial SSH user, we need to swap out and restore the password.
|
25
|
+
#
|
26
|
+
# We special-case the 'ubuntu' user since Amazon doesn't since the Canonical AMIs on EC2 don't set the password for
|
27
|
+
# this account, making any password prompt potentially confusing.
|
28
|
+
orig_password = fetch(:password)
|
29
|
+
set(:password, initial_ssh_user == 'ubuntu' ? nil : Capistrano::CLI.password_prompt("Password for #{initial_ssh_user} @ #{ip}: "))
|
22
30
|
|
23
31
|
task :_allow_root_ssh, :hosts => "#{initial_ssh_user}@#{ip}" do
|
24
|
-
rsudo "cp /home/#{initial_ssh_user}/.ssh/authorized_keys /root/.ssh/"
|
32
|
+
rsudo "mkdir -p /root/.ssh && cp /home/#{initial_ssh_user}/.ssh/authorized_keys /root/.ssh/"
|
25
33
|
end
|
26
34
|
|
27
35
|
begin
|
@@ -35,6 +43,9 @@ namespace :rubber do
|
|
35
43
|
retry
|
36
44
|
end
|
37
45
|
end
|
46
|
+
|
47
|
+
# Restore the original deploy password.
|
48
|
+
set(:password, orig_password)
|
38
49
|
end
|
39
50
|
|
40
51
|
# Forces a direct connection
|
@@ -285,10 +296,22 @@ namespace :rubber do
|
|
285
296
|
Install extra packages and gems.
|
286
297
|
DESC
|
287
298
|
task :install do
|
299
|
+
install_core_packages
|
288
300
|
install_packages
|
289
301
|
install_gems
|
290
302
|
end
|
291
303
|
|
304
|
+
desc <<-DESC
|
305
|
+
Install core packages that are needed before the general install_packages phase.
|
306
|
+
DESC
|
307
|
+
task :install_core_packages do
|
308
|
+
core_packages = [
|
309
|
+
'python-software-properties', # Needed for add-apt-repository, which we use for adding PPAs.
|
310
|
+
'bc' # Needed for comparing version numbers in bash, which we do for various setup functions.
|
311
|
+
]
|
312
|
+
rsudo "export DEBIAN_FRONTEND=noninteractive; apt-get -q -o Dpkg::Options::=--force-confold -y --force-yes install #{core_packages.join(' ')}"
|
313
|
+
end
|
314
|
+
|
292
315
|
desc <<-DESC
|
293
316
|
Install Ubuntu packages. Set 'packages' in rubber.yml to \
|
294
317
|
be an array of strings.
|
@@ -463,6 +486,7 @@ namespace :rubber do
|
|
463
486
|
expanded_pkg_list << pkg_spec
|
464
487
|
end
|
465
488
|
end
|
489
|
+
expanded_pkg_list << 'ec2-ami-tools' if rubber_env.cloud_provider == 'aws'
|
466
490
|
expanded_pkg_list.join(' ')
|
467
491
|
end
|
468
492
|
|
@@ -154,24 +154,24 @@ namespace :rubber do
|
|
154
154
|
return local_alias
|
155
155
|
end
|
156
156
|
|
157
|
-
def prepare_script(name, contents, stop_on_error_cmd=rubber_env.stop_on_error_cmd)
|
157
|
+
def prepare_script(name, contents, stop_on_error_cmd=rubber_env.stop_on_error_cmd, opts = {})
|
158
158
|
script = "/tmp/#{name}"
|
159
159
|
# this lets us abort a script if a command in the middle of it errors out
|
160
160
|
contents = "#{stop_on_error_cmd}\n#{contents}" if stop_on_error_cmd
|
161
|
-
put(contents, script)
|
161
|
+
put(contents, script, opts)
|
162
162
|
return script
|
163
163
|
end
|
164
164
|
|
165
165
|
def run_script(name, contents, opts = {})
|
166
166
|
args = opts.delete(:script_args)
|
167
|
-
script = prepare_script(name, contents)
|
167
|
+
script = prepare_script(name, contents, rubber_env.stop_on_error_cmd, opts)
|
168
168
|
run "bash #{script} #{args}", opts
|
169
169
|
end
|
170
170
|
|
171
171
|
def sudo_script(name, contents, opts = {})
|
172
172
|
user = opts.delete(:as)
|
173
173
|
args = opts.delete(:script_args)
|
174
|
-
script = prepare_script(name, contents)
|
174
|
+
script = prepare_script(name, contents, rubber_env.stop_on_error_cmd, opts)
|
175
175
|
|
176
176
|
sudo_args = user ? "-H -u #{user}" : ""
|
177
177
|
run "#{sudo} #{sudo_args} bash -l #{script} #{args}", opts
|
@@ -228,7 +228,10 @@ namespace :rubber do
|
|
228
228
|
def update_code_for_bootstrap
|
229
229
|
unless (fetch(:rubber_code_was_updated, false))
|
230
230
|
deploy.setup
|
231
|
+
logger.info "updating code for bootstrap"
|
232
|
+
set :rubber_updating_code_for_bootstrap_db, true
|
231
233
|
deploy.update_code
|
234
|
+
set :rubber_updating_code_for_bootstrap_db, false
|
232
235
|
end
|
233
236
|
end
|
234
237
|
|
data/lib/rubber/util.rb
CHANGED
data/lib/rubber/version.rb
CHANGED
@@ -90,11 +90,17 @@ task :cleanup, :except => { :no_release => true } do
|
|
90
90
|
end
|
91
91
|
|
92
92
|
if Rubber::Util.has_asset_pipeline?
|
93
|
-
# load asset pipeline
|
94
|
-
#
|
93
|
+
# load asset pipeline task, disable precompile from being triggered
|
94
|
+
# by deploy:update_code during bootstrap_db, and reorder to run after
|
95
|
+
# rubber:config has generated database.yml/etc.
|
95
96
|
load 'deploy/assets'
|
96
97
|
callbacks[:after].delete_if {|c| c.source == "deploy:assets:precompile"}
|
97
|
-
|
98
|
-
|
99
|
-
|
98
|
+
task :_skip_assets_precompile_if_bootstrapping_db do
|
99
|
+
if fetch(:rubber_updating_code_for_bootstrap_db, false)
|
100
|
+
logger.info "Skipping assets precompilation"
|
101
|
+
else
|
102
|
+
deploy.assets.precompile
|
103
|
+
end
|
104
|
+
end
|
105
|
+
after 'deploy:update_code', '_skip_assets_precompile_if_bootstrapping_db'
|
100
106
|
end
|
@@ -98,7 +98,20 @@ cloud_providers:
|
|
98
98
|
# If a spot instance request can't be fulfilled in 3 minutes, fallback to on-demand instance creation. If not set,
|
99
99
|
# the default is infinite.
|
100
100
|
# spot_instance_request_timeout: 180
|
101
|
-
|
101
|
+
|
102
|
+
digital_ocean:
|
103
|
+
# REQUIRED: The Digital Ocean region that you want to use.
|
104
|
+
#
|
105
|
+
# Options include
|
106
|
+
# New York 1
|
107
|
+
# Amsterdam 1
|
108
|
+
#
|
109
|
+
region: New York 1
|
110
|
+
|
111
|
+
# REQUIRED: The image name and type for creating instances.
|
112
|
+
image_id: Ubuntu 12.04 x64 Server
|
113
|
+
image_type: 512MB
|
114
|
+
|
102
115
|
# Use an alternate cloud provider supported by fog. This doesn't fully work
|
103
116
|
# yet due to differences in providers within fog, but gives you a starting
|
104
117
|
# point for contributing a new provider to rubber. See rubber/lib/rubber/cloud(.rb)
|
@@ -221,7 +234,7 @@ prompt_for_security_group_sync: true
|
|
221
234
|
# OPTIONAL: The packages to install on all instances
|
222
235
|
# You can install a specific version of a package by using a sub-array of pkg, version
|
223
236
|
# For example, packages: [[rake, 0.7.1], irb]
|
224
|
-
packages: [postfix, build-essential, git-core,
|
237
|
+
packages: [postfix, build-essential, git-core, libxslt-dev, ntp]
|
225
238
|
|
226
239
|
# OPTIONAL: gem sources to setup for rubygems
|
227
240
|
# gemsources: ["https://rubygems.org"]
|