kiel 0.2 → 0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -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 :image_by_tags, :wait_for_ec2, :wait_for_image
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 images..."
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
- # returns true, if an image with the given tags exists
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 image
159
- def delete_image image_name
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.2'
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-10 00:00:00.000000000 Z
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: -2182922364464276395
68
+ hash: 2193310327288113027
66
69
  required_rubygems_version: !ruby/object:Gem::Requirement
67
70
  none: false
68
71
  requirements: