awsborn 0.3.9 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.mdown CHANGED
@@ -65,7 +65,7 @@ Servers take five different directives:
65
65
  * `image_id` -- a valid EC2 AMI. Specify `:sudo_user` as an option if the AMI
66
66
  does not allow you to log in as root.
67
67
  * `security_group` -- a security group that you own.
68
- * `keys` -- one or more globs to public ssh keys. When the servers are running,
68
+ * `keys` -- one or more globs to public ssh key files. When the servers are running,
69
69
  `root` will be able to log in using any one of these keys.
70
70
  * `bootstrap_script` -- path to a script which will be run on each instance as
71
71
  soon as it is started. Use it to bootstrap `chef` and let `chef` take it from
@@ -87,7 +87,12 @@ Mandatory keys:
87
87
  * `:zone` -- the availability zone for the server. One of `:us_east_1a`, `:us_east_1b`,
88
88
  `:us_east_1c`, `:us_west_1a`, `:us_west_1b`, `:eu_west_1a`, `:eu_west_1b`.
89
89
  * `:disk` -- a hash of `device => volume-id`. Awsborn uses the disks to tell if a server
90
- is running or not (see *Launching a cluster*).
90
+ is running or not (see *Launching a cluster*). `volume-id` can also be an array
91
+ `[volume-id, :format]`, in which case `the_server.format_disk_on_device?(device)`
92
+ will return `true`. See `contrib/cookbooks/ec2-ebs` for example usage.
93
+
94
+ Optional keys:
95
+
91
96
  * `:ip` -- a domain name which translates to an elastic ip. If the domain name does not
92
97
  contain a full stop (dot) and `domain` has been specified above, the domain is added.
93
98
 
@@ -206,6 +211,7 @@ Awsborn integrates with [Chef Solo](http://github.com/opscode/chef). An example
206
211
  "ec2-ebs",
207
212
  "git",
208
213
  "gems",
214
+ "lumberjack"
209
215
  ]
210
216
  }
211
217
  end
@@ -218,7 +224,12 @@ Just add a `Rakefile` in the same directory:
218
224
  require './servers'
219
225
 
220
226
  You are now able to run `rake` to start all servers and run Chef on each of them.
221
- See `rake -T` for more options.
227
+ Other rake tasks include:
228
+
229
+ * `rake chef` - Run chef on all servers, or the ones specified with `host=name1,name2`.
230
+ * `rake chef:debug` - Ditto, but with chef's log level set to `debug`.
231
+ * `rake start` - Start all servers (or host=name1,name2) but don't run `chef`.
232
+
222
233
 
223
234
  ## Bugs and surprising features
224
235
 
@@ -227,7 +238,6 @@ No bugs are known at this time.
227
238
  ### Untested features
228
239
 
229
240
  * Launching without ssh keys. (I suppose certain AMIs would support that.)
230
- * Running without elastic ip.
231
241
 
232
242
  ## To do / Could do
233
243
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.9
1
+ 0.4.0
@@ -0,0 +1,24 @@
1
+ #!/bin/bash
2
+
3
+ echo '------------------'
4
+ echo 'Bootstrapping Chef'
5
+ echo
6
+
7
+ aptitude -y update
8
+ aptitude -y install gcc g++ curl build-essential \
9
+ libxml-ruby libxml2-dev \
10
+ ruby irb ri rdoc ruby1.8-dev libzlib-ruby libyaml-ruby libreadline-ruby \
11
+ libruby libruby-extras libopenssl-ruby \
12
+ libdbm-ruby libdbi-ruby libdbd-sqlite3-ruby \
13
+ sqlite3 libsqlite3-dev libsqlite3-ruby
14
+
15
+ curl -L 'http://rubyforge.org/frs/download.php/69365/rubygems-1.3.6.tgz' | tar zxf -
16
+ cd rubygems* && ruby setup.rb --no-ri --no-rdoc
17
+
18
+ ln -sfv /usr/bin/gem1.8 /usr/bin/gem
19
+
20
+ gem install chef ohai --no-ri --no-rdoc
21
+
22
+ echo
23
+ echo 'Bootstrapping Chef - done'
24
+ echo '-------------------------'
@@ -0,0 +1,38 @@
1
+ #
2
+ # Cookbook Name:: ec2-ebs
3
+ # Recipe:: default
4
+ #
5
+ # Assumes volumes are preformatted by YOU or specified as
6
+ # # in cluster:
7
+ # server :log_a, :zone => :eu_west_1a, :disk => {:sdf => ["vol-abcd1234", :format]}
8
+ # # in chef_dna:
9
+ # :ebs_volumes => [
10
+ # {:device => "sdf", :path => "/apps", :format => format_disk_on_device?("sdf")}
11
+ # ],
12
+
13
+
14
+ for ebs_volume in (node["ebs_volumes"] || [])
15
+ if (`grep /dev/#{ebs_volume[:device]} /etc/fstab` == "")
16
+ while not File.exists?("/dev/#{ebs_volume[:device]}")
17
+ Chef::Log.info("EBS volume device /dev/#{ebs_volume[:device]} not ready...")
18
+ sleep 5
19
+ end
20
+
21
+ execute "format #{ebs_volume[:device]}" do
22
+ command "mkfs -t ext3 -F /dev/#{ebs_volume[:device]}"
23
+ only_if { ebs_volume[:format] }
24
+ end
25
+
26
+ directory ebs_volume[:path] do
27
+ owner 'root'
28
+ group 'root'
29
+ mode 0755
30
+ end
31
+
32
+ mount ebs_volume[:path] do
33
+ device "/dev/#{ebs_volume[:device]}"
34
+ fstype "ext3"
35
+ action [:mount, :enable]
36
+ end
37
+ end
38
+ end
@@ -3,7 +3,7 @@ module Awsborn
3
3
  class ServerError < StandardError ; end
4
4
 
5
5
  class << self
6
- attr_writer :access_key_id, :secret_access_key, :logger, :remote_chef_path
6
+ attr_writer :access_key_id, :secret_access_key, :logger, :remote_chef_path, :chef_log_level
7
7
  attr_accessor :verbose
8
8
 
9
9
  Awsborn.verbose = true
@@ -44,7 +44,7 @@ module Awsborn
44
44
 
45
45
  def logger
46
46
  unless defined? @logger
47
- dir = [File.dirname(File.expand_path($0)), '/tmp'].find { |d| File.writable?(d) }
47
+ dir = [Dir.pwd, '/tmp'].find { |d| File.writable?(d) }
48
48
  if dir
49
49
  file = File.open(File.join(dir, 'awsborn.log'), 'a')
50
50
  file.sync = true
@@ -80,6 +80,10 @@ module Awsborn
80
80
  def verbose_output(message)
81
81
  puts message if Awsborn.verbose
82
82
  end
83
-
83
+
84
+ def chef_log_level
85
+ @chef_log_level || :info
86
+ end
87
+
84
88
  end
85
89
  end
@@ -26,10 +26,11 @@ module Awsborn
26
26
  tries += 1
27
27
  try_update
28
28
  rescue SecurityError => e
29
- if tries < 5
29
+ if tries < 8
30
30
  logger.debug e.message
31
- logger.debug "Sleeping, try #{tries}"
32
- sleep([2**tries, 15].min)
31
+ sleep_time = [2**tries, 30].min
32
+ logger.debug "Fingerprint try #{tries} failed, sleeping #{sleep_time} seconds"
33
+ sleep(sleep_time)
33
34
  retry
34
35
  else
35
36
  raise e
data/lib/awsborn/rake.rb CHANGED
@@ -7,36 +7,48 @@ module Awsborn
7
7
  default_klass.clusters.first
8
8
  end
9
9
 
10
- desc "Start all servers (if needed) and deploy with chef"
11
- task :default => [:start, :chef]
10
+ desc "Default: Start all servers (if needed) and deploy with chef."
11
+ task :all => [:start, "chef:run"]
12
+ task :default => :all
12
13
 
13
- desc "Start all servers"
14
- task :start do
15
- default_cluster.launch
14
+ desc "Start all servers (or host=name1,name2)."
15
+ task :start do |t,args|
16
+ hosts = args[:host] && args[:host].split(',')
17
+ default_cluster.launch hosts
16
18
  end
17
19
 
18
- desc "Run chef on all servers"
19
- task :chef => [:check_syntax] do
20
- default_cluster.each do |server|
21
- server.cook
20
+ desc "Run chef on all servers (or host=name1,name2)."
21
+ task :chef => "chef:run"
22
+
23
+ namespace :chef do
24
+ task :run => [:check_syntax] do |t,args|
25
+ hosts = args[:host] && args[:host].split(',')
26
+ default_cluster.each do |server|
27
+ server.cook if hosts.nil? || hosts.include?(server.name.to_s)
28
+ end
22
29
  end
23
- end
24
- task :cook => [:chef]
25
30
 
26
- desc "Check your cookbooks and config files for syntax errors"
27
- task :check_syntax do
28
- Dir["**/*.rb"].each do |recipe|
29
- RakeFileUtils.verbose(false) do
30
- sh %{ruby -c #{recipe} > /dev/null} do |ok, res|
31
- raise "Syntax error in #{recipe}" if not ok
31
+ desc "Run chef on all servers with log_level debug."
32
+ task :debug => [:set_chef_debug, :run]
33
+ task :set_chef_debug do
34
+ Awsborn.chef_log_level = :debug
35
+ end
36
+
37
+ desc "Check your cookbooks and config files for syntax errors."
38
+ task :check_syntax do
39
+ Dir["**/*.rb"].each do |recipe|
40
+ RakeFileUtils.verbose(false) do
41
+ sh %{ruby -c #{recipe} > /dev/null} do |ok, res|
42
+ raise "Syntax error in #{recipe}" if not ok
43
+ end
32
44
  end
33
45
  end
34
46
  end
35
- end
36
47
 
37
- desc "Create a new cookbook (with cookbook=name)"
38
- task :new_cookbook do
39
- create_cookbook("cookbooks")
48
+ desc "Create a new cookbook (with cookbook=name)."
49
+ task :new_cookbook do
50
+ create_cookbook("cookbooks")
51
+ end
40
52
  end
41
53
 
42
54
  def create_cookbook(dir)
@@ -57,7 +57,7 @@ module Awsborn
57
57
 
58
58
  def running?
59
59
  map = {}
60
- disk.values.each { |vol_id| map[vol_id] = ec2.instance_id_for_volume(vol_id) }
60
+ disk_volume_ids.each { |vol_id| map[vol_id] = ec2.instance_id_for_volume(vol_id) }
61
61
  ids = map.values.uniq
62
62
  if ids.size > 1
63
63
  raise ServerError, "Volumes for #{self.class.name}:#{name} are connected to several instances: #{map.inspect}"
@@ -153,13 +153,14 @@ module Awsborn
153
153
  logger.debug "Bootstrapping #{name}"
154
154
  script = bootstrap_script
155
155
  basename = File.basename(script)
156
- system "scp #{script} root@#{elastic_ip}:/tmp"
157
- system "ssh root@#{elastic_ip} 'cd /tmp && chmod 700 #{basename} && ./#{basename}'"
156
+ system "scp #{script} root@#{host_name}:/tmp"
157
+ system "ssh root@#{host_name} 'cd /tmp && chmod 700 #{basename} && ./#{basename}'"
158
158
  end
159
159
 
160
160
  def attach_volumes
161
161
  logger.debug "Attaching volumes #{disk.values.join(', ')} to #{name}"
162
- disk.each_pair do |device, volume|
162
+ disk.each_pair do |device, str_or_ary|
163
+ volume = str_or_ary.is_a?(Array) ? str_or_ary.first : str_or_ary
163
164
  device = "/dev/#{device}" if device.is_a?(Symbol) || ! device.match('/')
164
165
  res = ec2.attach_volume(volume, device)
165
166
  end
@@ -181,7 +182,7 @@ module Awsborn
181
182
  def run_chef
182
183
  logger.info "Running chef on #{host_name}"
183
184
  # Absolute path to config files to avoid a nasty irrational bug.
184
- sh "ssh root@#{host_name} \"cd #{Awsborn.remote_chef_path}; chef-solo -c #{Awsborn.remote_chef_path}/config/solo.rb -j #{Awsborn.remote_chef_path}/config/dna.json\""
185
+ sh "ssh root@#{host_name} \"cd #{Awsborn.remote_chef_path}; chef-solo -l #{Awsborn.chef_log_level} -c #{Awsborn.remote_chef_path}/config/solo.rb -j #{Awsborn.remote_chef_path}/config/dna.json\""
185
186
  end
186
187
 
187
188
  def ec2
@@ -189,17 +190,33 @@ module Awsborn
189
190
  end
190
191
 
191
192
  begin :accessors
192
- attr_accessor :name, :host_name, :logger
193
+ attr_accessor :name, :logger
193
194
  def host_name= (string)
194
195
  logger.debug "Setting host_name of #{name} to #{string}"
195
196
  @host_name = string
196
197
  end
198
+ def host_name
199
+ unless @host_name
200
+ logger.debug 'Looking up DNS name from volume ID'
201
+ self.host_name = aws_dns_name
202
+ logger.debug "got DNS name #{@host_name}"
203
+ update_known_hosts
204
+ end
205
+ @host_name
206
+ end
197
207
  def zone
198
208
  @options[:zone]
199
209
  end
200
210
  def disk
201
211
  @options[:disk]
202
212
  end
213
+ def disk_volume_ids
214
+ disk.values.map { |str_or_ary| str_or_ary.is_a?(Array) ? str_or_ary.first : str_or_ary }
215
+ end
216
+ def format_disk_on_device? (device)
217
+ volume = disk[device.to_sym]
218
+ volume.is_a?(Array) && volume.last == :format
219
+ end
203
220
  def image_id
204
221
  self.class.image_id
205
222
  end
@@ -22,8 +22,9 @@ module Awsborn
22
22
  @instances << instance
23
23
  end
24
24
 
25
- def launch
26
- running, missing = @instances.partition { |e| e.running? }
25
+ def launch (names)
26
+ requested = names.nil? ? @instances : @instances.select { |s| names.include?(s.name.to_s) }
27
+ running, missing = requested.partition { |e| e.running? }
27
28
  refresh_running(running) if running.any?
28
29
  start_missing_instances(missing) if missing.any?
29
30
  end
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 3
8
- - 9
9
- version: 0.3.9
7
+ - 4
8
+ - 0
9
+ version: 0.4.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - David Vrensk
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-06-09 00:00:00 +02:00
17
+ date: 2010-09-07 00:00:00 +02:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -101,6 +101,8 @@ files:
101
101
  - README.mdown
102
102
  - Rakefile
103
103
  - VERSION
104
+ - contrib/chef-bootstrap.sh
105
+ - contrib/cookbooks/ec2-ebs/recipes/default.rb
104
106
  - lib/awsborn.rb
105
107
  - lib/awsborn/awsborn.rb
106
108
  - lib/awsborn/ec2.rb