kiel 0.2 → 0.4
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/lib/kiel.rb +2 -0
- data/lib/kiel/cloud/aws.rb +12 -21
- data/lib/kiel/cloud/aws_base.rb +23 -0
- data/lib/kiel/cloud/right_aws.rb +158 -0
- metadata +8 -5
data/lib/kiel.rb
CHANGED
|
@@ -12,6 +12,8 @@ require 'kiel/cloud/aws'
|
|
|
12
12
|
# If one step fails, all subsequent installation steps might fail too. But when one step succeeds, that step can be
|
|
13
13
|
# used as base for all subsequence steps.
|
|
14
14
|
#
|
|
15
|
+
# Currently there are two different ways to access the AWS API: RightAWS and the aws-sdk gem.
|
|
16
|
+
#
|
|
15
17
|
# License:: Distributes under the MIT license
|
|
16
18
|
|
|
17
19
|
module Kiel
|
data/lib/kiel/cloud/aws.rb
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
require 'digest/sha1'
|
|
2
|
+
require 'kiel/cloud/aws_base'
|
|
2
3
|
|
|
3
4
|
module Kiel
|
|
4
5
|
module Cloud
|
|
5
|
-
INSTANCE_STARTUP_TIMEOUT = 120
|
|
6
|
-
RECOGNIZED_OPTIONS = [ :region, :credentials, :instance, :start_options ]
|
|
7
|
-
|
|
8
6
|
# Implements the connection to the Amazon Web Services (AWS). The current implementation works for one
|
|
9
7
|
# configured region. The default server is a small EC2 instance.
|
|
10
8
|
class AWS
|
|
9
|
+
include AWSBase
|
|
10
|
+
|
|
11
|
+
RECOGNIZED_OPTIONS = [ :region, :credentials, :instance, :start_options ]
|
|
12
|
+
|
|
11
13
|
# The contructor takes the following configuration options:
|
|
12
14
|
#
|
|
13
15
|
# :region:: A string naming the region to be used. If no region is given, the default region is used.
|
|
@@ -41,6 +43,7 @@ module Kiel
|
|
|
41
43
|
end
|
|
42
44
|
end
|
|
43
45
|
|
|
46
|
+
# Finds all images where the given tags apply
|
|
44
47
|
def all_images_by_tags tags
|
|
45
48
|
images = @ec2.images.with_owner('self').tagged( tags.first.first )
|
|
46
49
|
|
|
@@ -52,13 +55,6 @@ module Kiel
|
|
|
52
55
|
images
|
|
53
56
|
end
|
|
54
57
|
|
|
55
|
-
def image_by_tags tags
|
|
56
|
-
images = all_images_by_tags tags
|
|
57
|
-
|
|
58
|
-
raise "#{images.size} are tagged with the given tags: #{tags.inspect}" if images.size > 1
|
|
59
|
-
images.size == 1 ? images.first : nil
|
|
60
|
-
end
|
|
61
|
-
|
|
62
58
|
def wait_for_ec2 instance
|
|
63
59
|
puts "waiting for EC2 instance to start."
|
|
64
60
|
sleep_count = INSTANCE_STARTUP_TIMEOUT
|
|
@@ -83,7 +79,7 @@ module Kiel
|
|
|
83
79
|
puts ''
|
|
84
80
|
end
|
|
85
81
|
|
|
86
|
-
private :
|
|
82
|
+
private :wait_for_ec2, :wait_for_image
|
|
87
83
|
|
|
88
84
|
# starts a server instance in the cloud, returning a handle to that instance.
|
|
89
85
|
# the image is either named by an image id +:id => 'image_id'+ or by a set of tags that match for
|
|
@@ -118,7 +114,7 @@ module Kiel
|
|
|
118
114
|
|
|
119
115
|
puts "waiting 2 minutes before starting to take the image..."
|
|
120
116
|
sleep 120
|
|
121
|
-
puts "creating
|
|
117
|
+
puts "creating image..."
|
|
122
118
|
|
|
123
119
|
image = @ec2.images.create(
|
|
124
120
|
:instance_id => instance.id,
|
|
@@ -144,19 +140,14 @@ module Kiel
|
|
|
144
140
|
end
|
|
145
141
|
end
|
|
146
142
|
|
|
147
|
-
#
|
|
148
|
-
def exists? tags
|
|
149
|
-
raise ArgumentError, "AWS.exists? with empty tags" if tags.empty?
|
|
150
|
-
|
|
151
|
-
image_by_tags tags
|
|
152
|
-
end
|
|
153
|
-
|
|
143
|
+
# the public dns name of the given instance
|
|
154
144
|
def dns_name instance
|
|
155
145
|
instance.dns_name
|
|
156
146
|
end
|
|
157
147
|
|
|
158
|
-
# deletes the given
|
|
159
|
-
def delete_image
|
|
148
|
+
# deletes the given images by tags. For now this function is used just for cleanup during tests.
|
|
149
|
+
def delete_image tags
|
|
150
|
+
all_images_by_tags( tags ).each { | image | image.deregister }
|
|
160
151
|
end
|
|
161
152
|
end
|
|
162
153
|
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module Kiel
|
|
2
|
+
module Cloud
|
|
3
|
+
module AWSBase
|
|
4
|
+
INSTANCE_STARTUP_TIMEOUT = 120
|
|
5
|
+
|
|
6
|
+
def image_by_tags tags
|
|
7
|
+
images = all_images_by_tags tags
|
|
8
|
+
|
|
9
|
+
raise "#{images.size} are tagged with the given tags: #{tags.inspect}" if images.size > 1
|
|
10
|
+
images.size == 1 ? images.first : nil
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
private :image_by_tags
|
|
14
|
+
|
|
15
|
+
# returns true, if an image with the given tags exists
|
|
16
|
+
def exists? tags
|
|
17
|
+
raise ArgumentError, "AWS.exists? with empty tags" if tags.empty?
|
|
18
|
+
|
|
19
|
+
image_by_tags tags
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
require 'kiel/cloud/aws_base'
|
|
2
|
+
|
|
3
|
+
module Kiel
|
|
4
|
+
module Cloud
|
|
5
|
+
# Implements the connection to the Amazon Web Services (AWS) using the Right-AWS gem.
|
|
6
|
+
class RightAWS
|
|
7
|
+
include AWSBase
|
|
8
|
+
|
|
9
|
+
RECOGNIZED_OPTIONS = [ :region, :credentials, :instance, :start_options ]
|
|
10
|
+
|
|
11
|
+
# The contructor takes the following configuration options:
|
|
12
|
+
#
|
|
13
|
+
# :region:: A string naming the region to be used. If no region is given, North America is used by default.
|
|
14
|
+
#
|
|
15
|
+
# :credentials:: A hash containing the fields 'access_key_id' and 'secret_access_key' with the credential
|
|
16
|
+
# information to your amazon account.
|
|
17
|
+
#
|
|
18
|
+
# :instance:: An instance of the AWS::EC2. If that instance is given, no +credentials:+ should be given.
|
|
19
|
+
# Kiel::Cloud::AWS will instead use this instance.
|
|
20
|
+
#
|
|
21
|
+
# :start_options:: Possible options are :key_name and :security_groups to set the
|
|
22
|
+
# name of the used ssh key and a security group, where ssh is enabled.
|
|
23
|
+
def initialize options = {}
|
|
24
|
+
require 'right_aws'
|
|
25
|
+
|
|
26
|
+
options.each_key do | key |
|
|
27
|
+
raise ArgumentError, "unrecognized option \'#{key}\'" unless RECOGNIZED_OPTIONS.include? key
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
@ec2 = options[ :instance ]
|
|
31
|
+
@start_options = options[ :start_options ] || {}
|
|
32
|
+
|
|
33
|
+
if @ec2
|
|
34
|
+
puts "\'credentials\' ignored as an instance was given too" if options.key? :credentials
|
|
35
|
+
else
|
|
36
|
+
raise ArgumentError, 'no credentials given' unless options.key? :credentials
|
|
37
|
+
credentials = options[ :credentials ]
|
|
38
|
+
|
|
39
|
+
raise ArgumentError, 'no :access_key_id given within credentials' unless credentials.key? :access_key_id
|
|
40
|
+
raise ArgumentError, 'no :secret_access_key given within credentials' unless credentials.key? :secret_access_key
|
|
41
|
+
|
|
42
|
+
params = options.key?( :region ) ? { region: options[ :region ] } : {}
|
|
43
|
+
@ec2 = RightAws::Ec2.new credentials[ :access_key_id ], credentials[ :secret_access_key ], params
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Finds all images where the given tags apply
|
|
48
|
+
def all_images_by_tags tags
|
|
49
|
+
images = @ec2.describe_images_by_owner 'self'
|
|
50
|
+
|
|
51
|
+
images = images.select do | image |
|
|
52
|
+
image_tags = image[ :tags ]
|
|
53
|
+
image_tags.merge( tags ) == image_tags
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
images
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def wait_for_ec2 instance
|
|
60
|
+
puts "waiting for EC2 instance to start."
|
|
61
|
+
sleep 10 # added to reduce the likelihood of getting an "The instance ID 'i-xxxxxx' does not exist" message
|
|
62
|
+
sleep_count = INSTANCE_STARTUP_TIMEOUT
|
|
63
|
+
while @ec2.describe_instances( [ instance[ :aws_instance_id ] ] )[ 0 ][ :aws_state ] == 'pending' and sleep_count != 0 do
|
|
64
|
+
sleep 1
|
|
65
|
+
sleep_count = sleep_count - 1
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def wait_for_image image
|
|
70
|
+
image_state = 'pending'
|
|
71
|
+
while image_state == 'pending' do
|
|
72
|
+
begin
|
|
73
|
+
image_state = @ec2.describe_images_by_owner( 'self' ).detect{ | desc | desc[ :aws_id ] == image }
|
|
74
|
+
image_state = image_state[ :aws_state ]
|
|
75
|
+
rescue => e
|
|
76
|
+
puts "err: #{e.inspect}"
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
sleep 1
|
|
80
|
+
STDOUT.write '.'
|
|
81
|
+
end
|
|
82
|
+
puts ''
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
private :wait_for_ec2, :wait_for_image
|
|
86
|
+
|
|
87
|
+
# starts a server instance in the cloud, returning a handle to that instance.
|
|
88
|
+
# the image is either named by an image id +:id => 'image_id'+ or by a set of tags that match for
|
|
89
|
+
# just one image +:tags => { 'image_type' => 'application', 'base' => '34' }+
|
|
90
|
+
def start_instance image_name
|
|
91
|
+
options = @start_options.merge( if image_name.key?( :id )
|
|
92
|
+
{ image_id: image_name[ :id ] }
|
|
93
|
+
else
|
|
94
|
+
tags = image_name[ :tags ]
|
|
95
|
+
image = image_by_tags tags
|
|
96
|
+
raise RuntimeError, "no image with tags: \'#{tags}\' found to start an instance" unless image
|
|
97
|
+
|
|
98
|
+
{ image_id: image[ :aws_id ] }
|
|
99
|
+
end )
|
|
100
|
+
|
|
101
|
+
instance = @ec2.launch_instances(
|
|
102
|
+
options[ :image_id ], image_id: options[ :image_id ], key_name: options[ :key_name ], group_names: options[ :security_groups ] )
|
|
103
|
+
instance = instance[ 0 ]
|
|
104
|
+
|
|
105
|
+
begin
|
|
106
|
+
wait_for_ec2 instance
|
|
107
|
+
puts "ec2 instance \'#{dns_name instance}\' started."
|
|
108
|
+
rescue
|
|
109
|
+
stop_instance instance
|
|
110
|
+
raise
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
instance
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# store the given +instance+ and add the hash of +tags+ to the image.
|
|
117
|
+
def store_image instance, tags
|
|
118
|
+
begin
|
|
119
|
+
puts "waiting 2 minutes before starting to take the image..."
|
|
120
|
+
sleep 120
|
|
121
|
+
puts "creating image..."
|
|
122
|
+
|
|
123
|
+
image = @ec2.create_image(
|
|
124
|
+
instance[ :aws_instance_id ],
|
|
125
|
+
:no_reboot => true,
|
|
126
|
+
:description => "automaticaly created #{tags[ 'image_type' ]} image",
|
|
127
|
+
:name => "#{tags[ 'image_type' ]} #{Digest::SHA1.hexdigest tags.inspect}" )
|
|
128
|
+
|
|
129
|
+
puts "waiting for image to get ready..."
|
|
130
|
+
wait_for_image image
|
|
131
|
+
|
|
132
|
+
puts "image was created, adding tags..."
|
|
133
|
+
@ec2.create_tags( image, tags )
|
|
134
|
+
puts "tags added."
|
|
135
|
+
ensure
|
|
136
|
+
stop_instance instance
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# stops the given instance.
|
|
141
|
+
def stop_instance instance
|
|
142
|
+
@ec2.terminate_instances( [ instance[ :aws_instance_id ] ] )
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# the public dns name of the given instance
|
|
146
|
+
def dns_name instance
|
|
147
|
+
@ec2.describe_instances( [ instance[ :aws_instance_id ] ] )[ 0 ][ :dns_name ]
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# deletes the given images by tags. For now this function is used just for cleanup during tests.
|
|
151
|
+
def delete_image tags
|
|
152
|
+
all_images_by_tags( tags ).each do | image |
|
|
153
|
+
@ec2.deregister_image image[ :aws_id ]
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: kiel
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: '0.
|
|
4
|
+
version: '0.4'
|
|
5
5
|
prerelease:
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
@@ -9,10 +9,11 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2012-09-
|
|
12
|
+
date: 2012-09-13 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name:
|
|
16
|
+
- rake
|
|
16
17
|
- aws-sdk
|
|
17
18
|
- capistrano
|
|
18
19
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -32,15 +33,17 @@ dependencies:
|
|
|
32
33
|
description: ! "Kiel automates the process of creating rake tasks to produce Amazon
|
|
33
34
|
Machine Images (AMI). The basic idea behind Kiel\nis that an AMI can be best produced
|
|
34
35
|
by installing software step by step on a defined base and by having all that \nsteps
|
|
35
|
-
under source code control. On the way from a base image to the final AMI, produces
|
|
36
|
-
a new AMI with every step.\n"
|
|
36
|
+
under source code control. On the way from a base image to the final AMI, Kiel produces
|
|
37
|
+
a new AMI with every step\nand thus has some save points to start with.\n"
|
|
37
38
|
email: gemmaster@robitzki.de
|
|
38
39
|
executables: []
|
|
39
40
|
extensions: []
|
|
40
41
|
extra_rdoc_files: []
|
|
41
42
|
files:
|
|
42
43
|
- lib/kiel/cloud/aws.rb
|
|
44
|
+
- lib/kiel/cloud/aws_base.rb
|
|
43
45
|
- lib/kiel/cloud/mock.rb
|
|
46
|
+
- lib/kiel/cloud/right_aws.rb
|
|
44
47
|
- lib/kiel/scm/git.rb
|
|
45
48
|
- lib/kiel/scm/mock.rb
|
|
46
49
|
- lib/kiel/setup/capistrano.rb
|
|
@@ -62,7 +65,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
62
65
|
version: '0'
|
|
63
66
|
segments:
|
|
64
67
|
- 0
|
|
65
|
-
hash:
|
|
68
|
+
hash: 2193310327288113027
|
|
66
69
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
67
70
|
none: false
|
|
68
71
|
requirements:
|