awsborn 0.2.1 → 0.3.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/README.mdown +66 -1
- data/Rakefile +1 -0
- data/VERSION +1 -1
- data/lib/awsborn/awsborn.rb +22 -2
- data/lib/awsborn/git_branch.rb +30 -0
- data/lib/awsborn/rake.rb +64 -0
- data/lib/awsborn/server.rb +27 -2
- data/lib/awsborn.rb +1 -0
- metadata +24 -8
data/README.mdown
CHANGED
@@ -16,8 +16,8 @@ that are not running.
|
|
16
16
|
require 'awsborn'
|
17
17
|
|
18
18
|
# If not set, will be picked up from ENV['AMAZON_ACCESS_KEY_ID']
|
19
|
-
# and ENV['AMAZON_SECRET_ACCESS_KEY'].
|
20
19
|
Awsborn.access_key_id = 'AAAAAAAAAAAA'
|
20
|
+
# Can be picked up from ENV['AMAZON_SECRET_ACCESS_KEY'] or Keychain (OS X)
|
21
21
|
Awsborn.secret_access_key = 'KKKKKKKKKKKK'
|
22
22
|
|
23
23
|
# Logs to `awsborn.log` in current dir with level INFO by default.
|
@@ -155,6 +155,71 @@ This is what we use with the AMI above:
|
|
155
155
|
echo 'Bootstrapping Chef - done'
|
156
156
|
echo '-------------------------'
|
157
157
|
|
158
|
+
## Running with Chef Solo
|
159
|
+
|
160
|
+
Awsborn integrates with [Chef Solo](http://github.com/opscode/chef). An example from reality:
|
161
|
+
|
162
|
+
Awsborn.access_key_id = 'AKIAJHL53MPX7LPCKIFQ'
|
163
|
+
|
164
|
+
class LogServer < Awsborn::Server
|
165
|
+
instance_type :m1_small
|
166
|
+
image_id 'ami-2fc2e95b', :sudo_user => 'ubuntu'
|
167
|
+
security_group 'Basic web'
|
168
|
+
keys '../keys/*'
|
169
|
+
bootstrap_script 'chef-bootstrap.sh'
|
170
|
+
monitor true
|
171
|
+
|
172
|
+
cluster do
|
173
|
+
domain 'releware.net'
|
174
|
+
server :log_a, :zone => :eu_west_1a, :disk => {:sdf => "vol-a857b8c1"}, :ip => 'log-a'
|
175
|
+
server :log_b, :zone => :eu_west_1b, :disk => {:sdf => "vol-aa57b8c3"}, :ip => 'log-b'
|
176
|
+
end
|
177
|
+
|
178
|
+
def chef_dna
|
179
|
+
{
|
180
|
+
:user => "lumberjack",
|
181
|
+
:host => host_name,
|
182
|
+
:users => [
|
183
|
+
{
|
184
|
+
:username => "lumberjack",
|
185
|
+
:authorized_keys => key_data,
|
186
|
+
:gid => 1001,
|
187
|
+
:uid => 1001,
|
188
|
+
:sudo => true,
|
189
|
+
}
|
190
|
+
],
|
191
|
+
:packages => %w[
|
192
|
+
vim
|
193
|
+
heirloom-mailx
|
194
|
+
],
|
195
|
+
:gems => [
|
196
|
+
"rake"
|
197
|
+
],
|
198
|
+
:ebs_volumes => [
|
199
|
+
{:device => "sdf", :path => "/apps"}
|
200
|
+
],
|
201
|
+
:recipes => [
|
202
|
+
"packages",
|
203
|
+
"users",
|
204
|
+
"sudo",
|
205
|
+
"openssh",
|
206
|
+
"ec2-ebs",
|
207
|
+
"git",
|
208
|
+
"gems",
|
209
|
+
]
|
210
|
+
}
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
Just add a `Rakefile` in the same directory:
|
215
|
+
|
216
|
+
require 'awsborn'
|
217
|
+
include Awsborn::Chef::Rake
|
218
|
+
require './servers'
|
219
|
+
|
220
|
+
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.
|
222
|
+
|
158
223
|
## Bugs and surprising features
|
159
224
|
|
160
225
|
No bugs are known at this time.
|
data/Rakefile
CHANGED
@@ -11,6 +11,7 @@ begin
|
|
11
11
|
gem.homepage = "http://github.com/icehouse/awsborn"
|
12
12
|
gem.authors = ["David Vrensk"]
|
13
13
|
gem.add_dependency "icehouse-right_aws", ">= 1.11.0"
|
14
|
+
gem.add_dependency "json_pure", ">= 1.2.3"
|
14
15
|
gem.add_development_dependency "rspec", ">= 1.2.9"
|
15
16
|
gem.add_development_dependency "webmock", ">= 0.9.1"
|
16
17
|
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.0
|
data/lib/awsborn/awsborn.rb
CHANGED
@@ -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
|
6
|
+
attr_writer :access_key_id, :secret_access_key, :logger, :remote_chef_path
|
7
7
|
attr_accessor :verbose
|
8
8
|
|
9
9
|
Awsborn.verbose = true
|
@@ -13,7 +13,27 @@ module Awsborn
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def secret_access_key
|
16
|
-
@secret_access_key
|
16
|
+
unless @secret_access_key
|
17
|
+
@secret_access_key = ENV['AMAZON_SECRET_ACCESS_KEY']
|
18
|
+
if @secret_access_key.to_s == ''
|
19
|
+
@secret_access_key = secret_access_key_from_keychain(access_key_id)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
@secret_access_key
|
23
|
+
end
|
24
|
+
|
25
|
+
def secret_access_key_from_keychain (key_id)
|
26
|
+
@credentials ||= {}
|
27
|
+
unless @credentials[key_id]
|
28
|
+
dump = `security -q find-generic-password -a "#{key_id}" -g 2>&1`
|
29
|
+
secret_key = dump[/password: "(.*)"/, 1]
|
30
|
+
@credentials[key_id] = secret_key
|
31
|
+
end
|
32
|
+
@credentials[key_id]
|
33
|
+
end
|
34
|
+
|
35
|
+
def remote_chef_path
|
36
|
+
@remote_chef_path ||= '/etc/chef'
|
17
37
|
end
|
18
38
|
|
19
39
|
def logger
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Awsborn
|
2
|
+
class GitBranch
|
3
|
+
|
4
|
+
attr_reader :branch
|
5
|
+
|
6
|
+
def initialize (branch)
|
7
|
+
require 'git'
|
8
|
+
@branch = branch
|
9
|
+
end
|
10
|
+
|
11
|
+
def file (path)
|
12
|
+
path, file = File.split(path)
|
13
|
+
|
14
|
+
repo = Git.open(root)
|
15
|
+
tree = repo.branches[branch].gcommit.gtree
|
16
|
+
path.each { |dir| tree = tree.subtrees[dir] }
|
17
|
+
tree.blobs[file].contents
|
18
|
+
end
|
19
|
+
|
20
|
+
protected
|
21
|
+
|
22
|
+
def root
|
23
|
+
dir = File.expand_path('.')
|
24
|
+
while dir != '/'
|
25
|
+
return dir if File.directory?(File.join(dir, '.git'))
|
26
|
+
dir = File.dirname(dir)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/awsborn/rake.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
module Awsborn
|
2
|
+
module Chef
|
3
|
+
module Rake
|
4
|
+
|
5
|
+
def default_cluster
|
6
|
+
default_klass = Awsborn::Server.children.first
|
7
|
+
default_klass.clusters.first
|
8
|
+
end
|
9
|
+
|
10
|
+
desc "Start all servers (if needed) and deploy with chef"
|
11
|
+
task :default => [:start, :cook]
|
12
|
+
|
13
|
+
desc "Start all servers"
|
14
|
+
task :start do
|
15
|
+
default_cluster.launch
|
16
|
+
end
|
17
|
+
|
18
|
+
desc "Run chef on all servers"
|
19
|
+
task :cook => [:check_syntax] do
|
20
|
+
default_cluster.each do |server|
|
21
|
+
server.cook
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
desc "Check your cookbooks and config files for syntax errors"
|
26
|
+
task :check_syntax do
|
27
|
+
Dir["**/*.rb"].each do |recipe|
|
28
|
+
RakeFileUtils.verbose(false) do
|
29
|
+
sh %{ruby -c #{recipe} > /dev/null} do |ok, res|
|
30
|
+
raise "Syntax error in #{recipe}" if not ok
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
desc "Create a new cookbook (with cookbook=name)"
|
37
|
+
task :new_cookbook do
|
38
|
+
create_cookbook("cookbooks")
|
39
|
+
end
|
40
|
+
|
41
|
+
def create_cookbook(dir)
|
42
|
+
raise "Must provide a cookbook=" unless ENV["cookbook"]
|
43
|
+
puts "** Creating cookbook #{ENV["cookbook"]}"
|
44
|
+
sh "mkdir -p #{File.join(dir, ENV["cookbook"], "attributes")}"
|
45
|
+
sh "mkdir -p #{File.join(dir, ENV["cookbook"], "recipes")}"
|
46
|
+
sh "mkdir -p #{File.join(dir, ENV["cookbook"], "definitions")}"
|
47
|
+
sh "mkdir -p #{File.join(dir, ENV["cookbook"], "libraries")}"
|
48
|
+
sh "mkdir -p #{File.join(dir, ENV["cookbook"], "files", "default")}"
|
49
|
+
sh "mkdir -p #{File.join(dir, ENV["cookbook"], "templates", "default")}"
|
50
|
+
|
51
|
+
unless File.exists?(File.join(dir, ENV["cookbook"], "recipes", "default.rb"))
|
52
|
+
open(File.join(dir, ENV["cookbook"], "recipes", "default.rb"), "w") do |file|
|
53
|
+
file.puts <<-EOH
|
54
|
+
#
|
55
|
+
# Cookbook Name:: #{ENV["cookbook"]}
|
56
|
+
# Recipe:: default
|
57
|
+
#
|
58
|
+
EOH
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
data/lib/awsborn/server.rb
CHANGED
@@ -8,7 +8,11 @@ module Awsborn
|
|
8
8
|
end
|
9
9
|
|
10
10
|
class << self
|
11
|
-
attr_accessor :logger
|
11
|
+
attr_accessor :logger, :children, :clusters
|
12
|
+
def inherited (klass)
|
13
|
+
@children ||= []
|
14
|
+
@children << klass
|
15
|
+
end
|
12
16
|
def image_id (*args)
|
13
17
|
unless args.empty?
|
14
18
|
@image_id = args.first
|
@@ -42,7 +46,9 @@ module Awsborn
|
|
42
46
|
end
|
43
47
|
|
44
48
|
def cluster (&block)
|
45
|
-
|
49
|
+
@clusters ||= []
|
50
|
+
@clusters << ServerCluster.build(self, &block)
|
51
|
+
@clusters.last
|
46
52
|
end
|
47
53
|
def logger
|
48
54
|
@logger ||= Awsborn.logger
|
@@ -163,6 +169,25 @@ module Awsborn
|
|
163
169
|
end
|
164
170
|
end
|
165
171
|
|
172
|
+
def cook
|
173
|
+
upload_cookbooks
|
174
|
+
run_chef
|
175
|
+
end
|
176
|
+
|
177
|
+
def upload_cookbooks
|
178
|
+
logger.info "Uploading cookbooks to #{host_name}"
|
179
|
+
File.open("config/dna.json", "w") { |f| f.write(chef_dna.to_json) }
|
180
|
+
sh "rsync -rl --delete --exclude '.*' ./ root@#{host_name}:#{Awsborn.remote_chef_path}"
|
181
|
+
ensure
|
182
|
+
File.delete("config/dna.json")
|
183
|
+
end
|
184
|
+
|
185
|
+
def run_chef
|
186
|
+
logger.info "Running chef on #{host_name}"
|
187
|
+
# Absolute path to config files to avoid a nasty irrational bug.
|
188
|
+
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\""
|
189
|
+
end
|
190
|
+
|
166
191
|
def ec2
|
167
192
|
@ec2 ||= Ec2.new(zone)
|
168
193
|
end
|
data/lib/awsborn.rb
CHANGED
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
7
|
+
- 3
|
8
|
+
- 0
|
9
|
+
version: 0.3.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-04-
|
17
|
+
date: 2010-04-19 00:00:00 +02:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -32,9 +32,23 @@ dependencies:
|
|
32
32
|
type: :runtime
|
33
33
|
version_requirements: *id001
|
34
34
|
- !ruby/object:Gem::Dependency
|
35
|
-
name:
|
35
|
+
name: json_pure
|
36
36
|
prerelease: false
|
37
37
|
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
segments:
|
42
|
+
- 1
|
43
|
+
- 2
|
44
|
+
- 3
|
45
|
+
version: 1.2.3
|
46
|
+
type: :runtime
|
47
|
+
version_requirements: *id002
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: rspec
|
50
|
+
prerelease: false
|
51
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
38
52
|
requirements:
|
39
53
|
- - ">="
|
40
54
|
- !ruby/object:Gem::Version
|
@@ -44,11 +58,11 @@ dependencies:
|
|
44
58
|
- 9
|
45
59
|
version: 1.2.9
|
46
60
|
type: :development
|
47
|
-
version_requirements: *
|
61
|
+
version_requirements: *id003
|
48
62
|
- !ruby/object:Gem::Dependency
|
49
63
|
name: webmock
|
50
64
|
prerelease: false
|
51
|
-
requirement: &
|
65
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
52
66
|
requirements:
|
53
67
|
- - ">="
|
54
68
|
- !ruby/object:Gem::Version
|
@@ -58,7 +72,7 @@ dependencies:
|
|
58
72
|
- 1
|
59
73
|
version: 0.9.1
|
60
74
|
type: :development
|
61
|
-
version_requirements: *
|
75
|
+
version_requirements: *id004
|
62
76
|
description: Awsborn lets you define and launch a server cluster on Amazon EC2.
|
63
77
|
email: david@icehouse.se
|
64
78
|
executables: []
|
@@ -80,7 +94,9 @@ files:
|
|
80
94
|
- lib/awsborn/ec2.rb
|
81
95
|
- lib/awsborn/extensions/object.rb
|
82
96
|
- lib/awsborn/extensions/proc.rb
|
97
|
+
- lib/awsborn/git_branch.rb
|
83
98
|
- lib/awsborn/known_hosts_updater.rb
|
99
|
+
- lib/awsborn/rake.rb
|
84
100
|
- lib/awsborn/server.rb
|
85
101
|
- lib/awsborn/server_cluster.rb
|
86
102
|
- spec/awsborn_spec.rb
|