awsborn 0.1.1 → 0.2.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 +4 -0
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/lib/awsborn/awsborn.rb +3 -2
- data/lib/awsborn/ec2.rb +22 -10
- data/lib/awsborn/server.rb +60 -13
- data/lib/awsborn/server_cluster.rb +9 -9
- metadata +7 -7
data/README.mdown
CHANGED
@@ -30,6 +30,7 @@ that are not running.
|
|
30
30
|
security_group 'Basic web'
|
31
31
|
keys 'keys/*.pub'
|
32
32
|
bootstrap_script 'chef-bootstrap.sh'
|
33
|
+
monitor true
|
33
34
|
end
|
34
35
|
|
35
36
|
log_servers = LogServer.cluster do
|
@@ -179,6 +180,9 @@ attached and the other isn't, one of these things will happen:
|
|
179
180
|
* Hack RightAws to verify certificates.
|
180
181
|
* Elastic Load Balancing.
|
181
182
|
* Launch servers in parallel.
|
183
|
+
* Make `image_id` a hash with different AMIs for different instance types.
|
184
|
+
* Make `image_id` overridable per server.
|
185
|
+
|
182
186
|
|
183
187
|
## Note on Patches/Pull Requests
|
184
188
|
|
data/Rakefile
CHANGED
@@ -10,7 +10,7 @@ begin
|
|
10
10
|
gem.email = "david@icehouse.se"
|
11
11
|
gem.homepage = "http://github.com/icehouse/awsborn"
|
12
12
|
gem.authors = ["David Vrensk"]
|
13
|
-
gem.add_dependency "right_aws", ">= 1.
|
13
|
+
gem.add_dependency "icehouse-right_aws", ">= 1.11.0"
|
14
14
|
gem.add_development_dependency "rspec", ">= 1.2.9"
|
15
15
|
gem.add_development_dependency "webmock", ">= 0.9.1"
|
16
16
|
# 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.2.0
|
data/lib/awsborn/awsborn.rb
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
module Awsborn
|
2
2
|
class SecurityError < StandardError ; end
|
3
|
+
class ServerError < StandardError ; end
|
3
4
|
|
4
5
|
class << self
|
5
6
|
attr_writer :access_key_id, :secret_access_key, :logger
|
6
7
|
attr_accessor :verbose
|
7
|
-
|
8
|
+
|
8
9
|
Awsborn.verbose = true
|
9
|
-
|
10
|
+
|
10
11
|
def access_key_id
|
11
12
|
@access_key_id ||= ENV['AMAZON_ACCESS_KEY_ID']
|
12
13
|
end
|
data/lib/awsborn/ec2.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
module Awsborn
|
2
2
|
class Ec2
|
3
|
-
|
3
|
+
extend Forwardable
|
4
|
+
def_delegators :Awsborn, :logger
|
5
|
+
|
4
6
|
attr_accessor :instance_id
|
5
7
|
|
6
8
|
def connection
|
@@ -45,17 +47,12 @@ module Awsborn
|
|
45
47
|
def delete_key_pair (key_pair)
|
46
48
|
connection.delete_key_pair(key_pair.name)
|
47
49
|
end
|
48
|
-
|
49
|
-
def
|
50
|
+
|
51
|
+
def instance_id_for_volume (volume_id)
|
50
52
|
response = connection.describe_volumes(volume_id).first
|
51
|
-
|
52
|
-
self.instance_id = response[:aws_instance_id]
|
53
|
-
true
|
54
|
-
else
|
55
|
-
false
|
56
|
-
end
|
53
|
+
response[:aws_status] == 'in-use' ? response[:aws_instance_id] : nil
|
57
54
|
end
|
58
|
-
|
55
|
+
|
59
56
|
IP4_REGEXP = /^(\d{1,3}\.){3}\d{1,3}$/
|
60
57
|
|
61
58
|
def associate_address (address)
|
@@ -83,5 +80,20 @@ module Awsborn
|
|
83
80
|
def attach_volume (volume, device)
|
84
81
|
connection.attach_volume(volume, instance_id, device)
|
85
82
|
end
|
83
|
+
|
84
|
+
def monitoring?
|
85
|
+
%w[enabled pending].include?(describe_instance[:monitoring_state])
|
86
|
+
end
|
87
|
+
|
88
|
+
def monitor
|
89
|
+
logger.debug "Activating monitoring for #{instance_id}"
|
90
|
+
connection.monitor_instances(instance_id)
|
91
|
+
end
|
92
|
+
|
93
|
+
def unmonitor
|
94
|
+
logger.debug "Deactivating monitoring for #{instance_id}"
|
95
|
+
connection.unmonitor_instances(instance_id)
|
96
|
+
end
|
97
|
+
|
86
98
|
end
|
87
99
|
end
|
data/lib/awsborn/server.rb
CHANGED
@@ -36,6 +36,10 @@ module Awsborn
|
|
36
36
|
@bootstrap_script = args.first unless args.empty?
|
37
37
|
@bootstrap_script
|
38
38
|
end
|
39
|
+
def monitor (*args)
|
40
|
+
@monitor = args.first unless args.empty?
|
41
|
+
@monitor
|
42
|
+
end
|
39
43
|
|
40
44
|
def cluster (&block)
|
41
45
|
ServerCluster.build self, &block
|
@@ -45,12 +49,37 @@ module Awsborn
|
|
45
49
|
end
|
46
50
|
end
|
47
51
|
|
48
|
-
def
|
49
|
-
|
50
|
-
ec2.
|
52
|
+
def running?
|
53
|
+
map = {}
|
54
|
+
disk.values.each { |vol_id| map[vol_id] = ec2.instance_id_for_volume(vol_id) }
|
55
|
+
ids = map.values.uniq
|
56
|
+
if ids.size > 1
|
57
|
+
raise ServerError, "Volumes for #{self.class.name}:#{name} are connected to several instances: #{map.inspect}"
|
58
|
+
end
|
59
|
+
ec2.instance_id = ids.first
|
51
60
|
end
|
52
|
-
alias :running? :one_of_my_disks_is_attached_to_a_running_instance?
|
53
61
|
|
62
|
+
def refresh
|
63
|
+
start_or_stop_monitoring unless monitor.nil?
|
64
|
+
associate_address if elastic_ip
|
65
|
+
|
66
|
+
begin
|
67
|
+
update_known_hosts
|
68
|
+
install_ssh_keys if keys
|
69
|
+
rescue SecurityError => e
|
70
|
+
logger.warn "Could not update known_hosts for #{name}:"
|
71
|
+
logger.warn e
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def start_or_stop_monitoring
|
76
|
+
if monitor && ! ec2.monitoring?
|
77
|
+
ec2.monitor
|
78
|
+
elsif ec2.monitoring? && ! monitor
|
79
|
+
ec2.unmonitor
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
54
83
|
def start (key_pair)
|
55
84
|
launch_instance(key_pair)
|
56
85
|
|
@@ -71,7 +100,8 @@ module Awsborn
|
|
71
100
|
:instance_type => constant(instance_type),
|
72
101
|
:availability_zone => constant(zone),
|
73
102
|
:key_name => key_pair.name,
|
74
|
-
:group_ids => security_group
|
103
|
+
:group_ids => security_group,
|
104
|
+
:monitor_enabled => monitor
|
75
105
|
)
|
76
106
|
logger.debug @launch_response
|
77
107
|
|
@@ -83,33 +113,42 @@ module Awsborn
|
|
83
113
|
KnownHostsUpdater.update_for_server self
|
84
114
|
end
|
85
115
|
|
86
|
-
def install_ssh_keys (temp_key_pair)
|
87
|
-
|
88
|
-
|
89
|
-
|
116
|
+
def install_ssh_keys (temp_key_pair = nil)
|
117
|
+
logger.debug "Installing ssh keys on #{name}"
|
118
|
+
raise ArgumentError, "No host_name for #{name}" unless host_name
|
119
|
+
install_ssh_keys_for_sudo_user_or_root (temp_key_pair)
|
120
|
+
copy_sudo_users_keys_to_root if sudo_user
|
121
|
+
end
|
122
|
+
|
123
|
+
def install_ssh_keys_for_sudo_user_or_root (temp_key_pair)
|
124
|
+
current_key = "-i #{temp_key_pair.path}" if temp_key_pair
|
125
|
+
IO.popen("ssh #{current_key} #{sudo_user || 'root'}@#{host_name} 'cat > .ssh/authorized_keys'", "w") do |pipe|
|
90
126
|
pipe.puts key_data
|
91
127
|
end
|
92
|
-
if sudo_user
|
93
|
-
system("ssh #{sudo_user}@#{aws_dns_name} 'sudo cp .ssh/authorized_keys /root/.ssh/authorized_keys'")
|
94
|
-
end
|
95
128
|
end
|
96
|
-
|
129
|
+
|
97
130
|
def key_data
|
98
131
|
Dir[*keys].inject([]) do |memo, file_name|
|
99
132
|
memo + File.readlines(file_name).map { |line| line.chomp }
|
100
133
|
end.join("\n")
|
101
134
|
end
|
102
135
|
|
136
|
+
def copy_sudo_users_keys_to_root
|
137
|
+
system("ssh #{sudo_user}@#{host_name} 'sudo cp .ssh/authorized_keys /root/.ssh/authorized_keys'")
|
138
|
+
end
|
139
|
+
|
103
140
|
def path_relative_to_script (path)
|
104
141
|
File.join(File.dirname(File.expand_path($0)), path)
|
105
142
|
end
|
106
143
|
|
107
144
|
def associate_address
|
145
|
+
logger.debug "Associating address #{elastic_ip} to #{name}"
|
108
146
|
ec2.associate_address(elastic_ip)
|
109
147
|
self.host_name = elastic_ip
|
110
148
|
end
|
111
149
|
|
112
150
|
def bootstrap
|
151
|
+
logger.debug "Bootstrapping #{name}"
|
113
152
|
script = path_relative_to_script(bootstrap_script)
|
114
153
|
basename = File.basename(script)
|
115
154
|
system "scp #{script} root@#{elastic_ip}:/tmp"
|
@@ -117,6 +156,7 @@ module Awsborn
|
|
117
156
|
end
|
118
157
|
|
119
158
|
def attach_volumes
|
159
|
+
logger.debug "Attaching volumes #{disk.values.join(', ')} to #{name}"
|
120
160
|
disk.each_pair do |device, volume|
|
121
161
|
device = "/dev/#{device}" if device.is_a?(Symbol) || ! device.match('/')
|
122
162
|
res = ec2.attach_volume(volume, device)
|
@@ -129,6 +169,10 @@ module Awsborn
|
|
129
169
|
|
130
170
|
begin :accessors
|
131
171
|
attr_accessor :name, :host_name, :logger
|
172
|
+
def host_name= (string)
|
173
|
+
logger.debug "Setting host_name of #{name} to #{string}"
|
174
|
+
@host_name = string
|
175
|
+
end
|
132
176
|
def zone
|
133
177
|
@options[:zone]
|
134
178
|
end
|
@@ -153,6 +197,9 @@ module Awsborn
|
|
153
197
|
def keys
|
154
198
|
@options[:keys] || self.class.keys
|
155
199
|
end
|
200
|
+
def monitor
|
201
|
+
@options[:monitor] || self.class.monitor
|
202
|
+
end
|
156
203
|
def elastic_ip
|
157
204
|
@options[:ip]
|
158
205
|
end
|
@@ -23,19 +23,19 @@ module Awsborn
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def launch
|
26
|
-
|
26
|
+
running, missing = @instances.partition { |e| e.running? }
|
27
|
+
refresh_running(running) if running.any?
|
28
|
+
start_missing_instances(missing) if missing.any?
|
27
29
|
end
|
28
30
|
|
29
|
-
def
|
30
|
-
|
31
|
-
return if to_start.empty?
|
32
|
-
generate_key_pair(to_start)
|
33
|
-
to_start.each { |e| e.start(@key_pair) }
|
34
|
-
delete_key_pair(to_start)
|
31
|
+
def refresh_running (instances)
|
32
|
+
instances.each { |e| e.refresh }
|
35
33
|
end
|
36
34
|
|
37
|
-
def
|
38
|
-
|
35
|
+
def start_missing_instances (instances)
|
36
|
+
generate_key_pair(instances)
|
37
|
+
instances.each { |e| e.start(@key_pair) }
|
38
|
+
delete_key_pair(instances)
|
39
39
|
end
|
40
40
|
|
41
41
|
def generate_key_pair (instances)
|
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
|
+
- 2
|
8
|
+
- 0
|
9
|
+
version: 0.2.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- David Vrensk
|
@@ -14,11 +14,11 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-04-
|
17
|
+
date: 2010-04-14 00:00:00 +02:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
|
-
name: right_aws
|
21
|
+
name: icehouse-right_aws
|
22
22
|
prerelease: false
|
23
23
|
requirement: &id001 !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
@@ -26,9 +26,9 @@ dependencies:
|
|
26
26
|
- !ruby/object:Gem::Version
|
27
27
|
segments:
|
28
28
|
- 1
|
29
|
-
-
|
29
|
+
- 11
|
30
30
|
- 0
|
31
|
-
version: 1.
|
31
|
+
version: 1.11.0
|
32
32
|
type: :runtime
|
33
33
|
version_requirements: *id001
|
34
34
|
- !ruby/object:Gem::Dependency
|