ec2-starter 0.1.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/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ gem "amazon-ec2", ">= 0.9.17"
5
+ gem 'net-ssh', '>= 2.1.4'
6
+
7
+ # Add dependencies to develop your gem here.
8
+ # Include everything needed to run rake, tests, features, etc.
9
+ group :development do
10
+ gem "shoulda", ">= 0"
11
+ gem "bundler", "~> 1.0.0"
12
+ gem "jeweler", "~> 1.5.2"
13
+ gem "rcov", ">= 0"
14
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,26 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ amazon-ec2 (0.9.17)
5
+ xml-simple (>= 1.0.12)
6
+ git (1.2.5)
7
+ jeweler (1.5.2)
8
+ bundler (~> 1.0.0)
9
+ git (>= 1.2.5)
10
+ rake
11
+ net-ssh (2.1.4)
12
+ rake (0.9.2)
13
+ rcov (0.9.9)
14
+ shoulda (2.11.3)
15
+ xml-simple (1.1.0)
16
+
17
+ PLATFORMS
18
+ ruby
19
+
20
+ DEPENDENCIES
21
+ amazon-ec2 (>= 0.9.17)
22
+ bundler (~> 1.0.0)
23
+ jeweler (~> 1.5.2)
24
+ net-ssh (>= 2.1.4)
25
+ rcov
26
+ shoulda
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Oliver Kiessler
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,12 @@
1
+ ec2-starter
2
+ -----------
3
+
4
+ Very Ruby DSL to perform standard tasks on a single EC2 instance. With this you can start an instance, assign an IP, assign volumes and perform SSH shell commands.
5
+
6
+ See example.rb
7
+
8
+ Copyright
9
+ ---------
10
+
11
+ Copyright (c) 2011 Oliver Kiessler. See LICENSE.txt for
12
+ further details.
data/Rakefile ADDED
@@ -0,0 +1,50 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'rake'
11
+
12
+ require 'jeweler'
13
+ Jeweler::Tasks.new do |gem|
14
+ gem.name = "ec2-starter"
15
+ gem.homepage = "http://github.com/okiess/ec2-starter"
16
+ gem.license = "MIT"
17
+ gem.summary = %Q{Very simple EC2 instance starter}
18
+ gem.description = %Q{Very simple EC2 instance starter for single server deployments}
19
+ gem.email = "kiessler@inceedo.com"
20
+ gem.authors = ["Oliver Kiessler"]
21
+ gem.add_runtime_dependency 'amazon-ec2'
22
+ gem.add_development_dependency 'net-ssh'
23
+ end
24
+ Jeweler::RubygemsDotOrgTasks.new
25
+
26
+ require 'rake/testtask'
27
+ Rake::TestTask.new(:test) do |test|
28
+ test.libs << 'lib' << 'test'
29
+ test.pattern = 'test/**/test_*.rb'
30
+ test.verbose = true
31
+ end
32
+
33
+ require 'rcov/rcovtask'
34
+ Rcov::RcovTask.new do |test|
35
+ test.libs << 'test'
36
+ test.pattern = 'test/**/test_*.rb'
37
+ test.verbose = true
38
+ end
39
+
40
+ task :default => :test
41
+
42
+ require 'rake/rdoctask'
43
+ Rake::RDocTask.new do |rdoc|
44
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
45
+
46
+ rdoc.rdoc_dir = 'rdoc'
47
+ rdoc.title = "ec2-starter #{version}"
48
+ rdoc.rdoc_files.include('README*')
49
+ rdoc.rdoc_files.include('lib/**/*.rb')
50
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/example.rb ADDED
@@ -0,0 +1,26 @@
1
+ require "lib/ec2-starter"
2
+
3
+ service_options = {
4
+ :access_key_id => "YOUR KEY",
5
+ :secret_access_key => "YOUR SECRET",
6
+ :server => "eu-west-1.ec2.amazonaws.com" # Target Zone
7
+ }
8
+
9
+ start_options = {
10
+ :instance_type => "t1.micro",
11
+ :key_name => "YOUR KEY",
12
+ :availability_zone => "eu-west-1a",
13
+ :architecture => "x86_64",
14
+ :kernel_id => 'aki-4feec43b', # your kernel, remove if not needed
15
+ :ssh_user => 'deploy',
16
+ :ssh_keys => ['/Users/your_user/.ssh/your_key']
17
+ :sudo_password => nil # set if necessary
18
+ }
19
+
20
+ Ec2Starter.start 'YOUR AMI_ID', service_options, start_options do
21
+ ip 'YOUR ELASTIC IP'
22
+ volume :volume_id => 'YOUR VOLUME', :mount_point => '/dev/sdf'
23
+
24
+ command :sudo => '/root/attach_volume.sh' # Shell command on the instance
25
+ command '/home/your_user/some_script.sh'
26
+ end
data/lib/.DS_Store ADDED
Binary file
@@ -0,0 +1,8 @@
1
+ require 'rubygems'
2
+ gem "net-ssh"
3
+ require 'net/ssh'
4
+ gem 'amazon-ec2'
5
+ require 'AWS'
6
+
7
+ require File.dirname(__FILE__) + '/ec2-starter/starter'
8
+ require File.dirname(__FILE__) + '/ec2-starter/execution'
@@ -0,0 +1,148 @@
1
+ module Ec2Starter
2
+ class Execution
3
+ attr_accessor :ec2_instance, :dns_name
4
+
5
+ def initialize(ec2_instance)
6
+ @ec2_instance = ec2_instance
7
+ end
8
+
9
+ def start
10
+ success = false
11
+ result = launch_ami(@ec2_instance.ami_id)
12
+ instance_id = result.instancesSet.item[0].instanceId
13
+ puts "=> Starting Instance Id: #{instance_id.white}"
14
+
15
+ instance_state = nil
16
+ while(instance_state != 'running')
17
+ instance_state, @dns_name = get_instance_state(instance_id)
18
+ puts "=> Checking for running state... #{output_running_state(instance_state)}"
19
+ puts "=> Public DNS: #{@dns_name.white}" if instance_state == 'running'
20
+ sleep 10 unless instance_state == 'running'
21
+ end
22
+
23
+ if @ec2_instance.ips.size > 0
24
+ result = ec2.associate_address(:instance_id => instance_id, :public_ip => @ec2_instance.ips.first)
25
+ puts "=> Elastic IP: #{@ec2_instance.ips.first.white}" if result["return"] == "true"
26
+ else
27
+ skip_ip = true
28
+ end
29
+ if result["return"] == "true" or skip_ip
30
+ if @ec2_instance.volumes.size > 0
31
+ result = ec2.attach_volume(:volume_id => @ec2_instance.volumes.first[:volume_id], :instance_id => instance_id,
32
+ :device => @ec2_instance.volumes.first[:mount_point])
33
+
34
+ volume_state = nil
35
+ while(volume_state != 'attached')
36
+ volume_state = get_volume_state(@ec2_instance.volumes.first[:volume_id])
37
+ puts "=> Checking for attachment state... #{output_running_state(volume_state)}"
38
+ sleep 10 unless volume_state == 'attached'
39
+ end
40
+
41
+ success = true
42
+ puts "=> EBS Volume attached: #{@ec2_instance.volumes.first[:volume_id]}"
43
+ end
44
+ if @ec2_instance.commands.size > 0
45
+ ip = @ec2_instance.ips.first || @dns_name
46
+ system("ssh-keygen -R #{ip}")
47
+ i = 0
48
+ while(i < 3) do
49
+ begin
50
+ ssh
51
+ break
52
+ rescue => e
53
+ puts e.message
54
+ puts "Retrying in 10sec..."
55
+ sleep 10
56
+ end
57
+ i += 1
58
+ end
59
+ success = true
60
+ puts "=> SSH Commands were executed!"
61
+ end
62
+ else
63
+ puts "=> Could not assign Elastic IP!"
64
+ end
65
+
66
+ unless success
67
+ puts "Terminating instance: #{instance_id}".red
68
+ @ec2.terminate_instances(:instance_id => instance_id)
69
+ end
70
+ end
71
+
72
+ def ssh
73
+ ip = @ec2_instance.ips.first || @dns_name
74
+ Net::SSH.start(ip, @ec2_instance.default_options[:ssh_user], :keys => @ec2_instance.default_options[:ssh_keys]) do |ssh|
75
+ @ec2_instance.commands.each do |command|
76
+ if command.is_a?(String)
77
+ ssh.exec(command)
78
+ elsif command.is_a?(Hash) and command.include?(:sudo)
79
+ ssh.sudo @ec2_instance.default_options[:sudo_password], command[:sudo]
80
+ end
81
+ end
82
+ ssh.close
83
+ end
84
+ end
85
+
86
+ def ec2
87
+ @ec2 ||= AWS::EC2::Base.new(:access_key_id => @ec2_instance.service_options[:access_key_id],
88
+ :secret_access_key => @ec2_instance.service_options[:secret_access_key],
89
+ :server => @ec2_instance.service_options[:server])
90
+ end
91
+
92
+ def get_instance_state(instance_id)
93
+ result = ec2.describe_instances(:instance_id => instance_id)
94
+ instance_state = result["reservationSet"]["item"].first["instancesSet"]["item"].first["instanceState"]["name"]
95
+ dns_name = result["reservationSet"]["item"].first["instancesSet"]["item"].first["dnsName"]
96
+ return instance_state, dns_name
97
+ end
98
+
99
+ def get_volume_state(volume_id)
100
+ result = ec2.describe_volumes(:volume_id => volume_id)
101
+ volume_state = result["volumeSet"]["item"].first["attachmentSet"]["item"].first["status"]
102
+ return volume_state
103
+ end
104
+
105
+ def launch_ami(ami_id, options = {})
106
+ default_options = @ec2_instance.default_options.merge(:image_id => ami_id).merge(options)
107
+ run_options = default_options.merge(options)
108
+ puts "Launch Options: #{run_options.inspect}"
109
+ ec2.run_instances(run_options)
110
+ end
111
+
112
+ def output_running_state(running_state)
113
+ if running_state == 'running' or running_state == 'attached'
114
+ running_state.green
115
+ elsif running_state == 'terminated' or running_state == 'shutting-down'
116
+ running_state.red
117
+ elsif running_state == 'pending' or running_state == 'attaching'
118
+ running_state.yellow
119
+ else
120
+ running_state
121
+ end
122
+ end
123
+ end
124
+ end
125
+
126
+ class String
127
+ def green
128
+ "\033[32m#{self}\033[0m"
129
+ end
130
+
131
+ def red
132
+ "\033[31m#{self}\033[0m"
133
+ end
134
+
135
+ def yellow
136
+ "\033[33m#{self}\033[0m"
137
+ end
138
+
139
+ def white
140
+ "\033[1m#{self}\033[0m"
141
+ end
142
+ end
143
+
144
+ class Net::SSH::Connection::Session
145
+ def sudo(password, command)
146
+ exec %Q%echo "#{password}" | sudo -S #{command}%
147
+ end
148
+ end
@@ -0,0 +1,34 @@
1
+ module Ec2Starter
2
+ def self.start(ami_id, service_options, run_options, &block)
3
+ instance = Instance.new(ami_id, service_options, run_options)
4
+ instance.instance_eval(&block)
5
+ ec2_starter = Ec2Starter::Execution.new(instance)
6
+ ec2_starter.start
7
+ return instance
8
+ end
9
+
10
+ class Instance
11
+ attr_accessor :service_options, :default_options, :ami_id, :instance_id, :ips, :volumes, :commands
12
+
13
+ def initialize(ami_id, service_options, options)
14
+ @ami_id = ami_id.to_s
15
+ @ips = []
16
+ @volumes = []
17
+ @commands = []
18
+ @default_options = {}.merge(options)
19
+ @service_options = {}.merge(service_options)
20
+ end
21
+
22
+ def ip(ip_address)
23
+ @ips << ip_address
24
+ end
25
+
26
+ def volume(volume_hash)
27
+ @volumes << volume_hash
28
+ end
29
+
30
+ def command(command)
31
+ @commands << command
32
+ end
33
+ end
34
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,18 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'test/unit'
11
+ require 'shoulda'
12
+
13
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
15
+ require 'ec2-starter'
16
+
17
+ class Test::Unit::TestCase
18
+ end
@@ -0,0 +1,7 @@
1
+ require 'helper'
2
+
3
+ class TestEc2Starter < Test::Unit::TestCase
4
+ should "probably rename this file and start testing for real" do
5
+ flunk "hey buddy, you should probably rename this file and start testing for real"
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,199 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ec2-starter
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Oliver Kiessler
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2012-06-05 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: amazon-ec2
22
+ version_requirements: &id001 !ruby/object:Gem::Requirement
23
+ none: false
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ hash: 25
28
+ segments:
29
+ - 0
30
+ - 9
31
+ - 17
32
+ version: 0.9.17
33
+ type: :runtime
34
+ requirement: *id001
35
+ prerelease: false
36
+ - !ruby/object:Gem::Dependency
37
+ name: net-ssh
38
+ version_requirements: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 2
46
+ - 1
47
+ - 4
48
+ version: 2.1.4
49
+ type: :runtime
50
+ requirement: *id002
51
+ prerelease: false
52
+ - !ruby/object:Gem::Dependency
53
+ name: shoulda
54
+ version_requirements: &id003 !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ hash: 3
60
+ segments:
61
+ - 0
62
+ version: "0"
63
+ type: :development
64
+ requirement: *id003
65
+ prerelease: false
66
+ - !ruby/object:Gem::Dependency
67
+ name: bundler
68
+ version_requirements: &id004 !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ~>
72
+ - !ruby/object:Gem::Version
73
+ hash: 23
74
+ segments:
75
+ - 1
76
+ - 0
77
+ - 0
78
+ version: 1.0.0
79
+ type: :development
80
+ requirement: *id004
81
+ prerelease: false
82
+ - !ruby/object:Gem::Dependency
83
+ name: jeweler
84
+ version_requirements: &id005 !ruby/object:Gem::Requirement
85
+ none: false
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ hash: 7
90
+ segments:
91
+ - 1
92
+ - 5
93
+ - 2
94
+ version: 1.5.2
95
+ type: :development
96
+ requirement: *id005
97
+ prerelease: false
98
+ - !ruby/object:Gem::Dependency
99
+ name: rcov
100
+ version_requirements: &id006 !ruby/object:Gem::Requirement
101
+ none: false
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ hash: 3
106
+ segments:
107
+ - 0
108
+ version: "0"
109
+ type: :development
110
+ requirement: *id006
111
+ prerelease: false
112
+ - !ruby/object:Gem::Dependency
113
+ name: amazon-ec2
114
+ version_requirements: &id007 !ruby/object:Gem::Requirement
115
+ none: false
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ hash: 3
120
+ segments:
121
+ - 0
122
+ version: "0"
123
+ type: :runtime
124
+ requirement: *id007
125
+ prerelease: false
126
+ - !ruby/object:Gem::Dependency
127
+ name: net-ssh
128
+ version_requirements: &id008 !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ">="
132
+ - !ruby/object:Gem::Version
133
+ hash: 3
134
+ segments:
135
+ - 0
136
+ version: "0"
137
+ type: :development
138
+ requirement: *id008
139
+ prerelease: false
140
+ description: Very simple EC2 instance starter for single server deployments
141
+ email: kiessler@inceedo.com
142
+ executables: []
143
+
144
+ extensions: []
145
+
146
+ extra_rdoc_files:
147
+ - LICENSE.txt
148
+ - README.md
149
+ files:
150
+ - .document
151
+ - Gemfile
152
+ - Gemfile.lock
153
+ - LICENSE.txt
154
+ - README.md
155
+ - Rakefile
156
+ - VERSION
157
+ - example.rb
158
+ - lib/.DS_Store
159
+ - lib/ec2-starter.rb
160
+ - lib/ec2-starter/execution.rb
161
+ - lib/ec2-starter/starter.rb
162
+ - test/helper.rb
163
+ - test/test_ec2-starter.rb
164
+ homepage: http://github.com/okiess/ec2-starter
165
+ licenses:
166
+ - MIT
167
+ post_install_message:
168
+ rdoc_options: []
169
+
170
+ require_paths:
171
+ - lib
172
+ required_ruby_version: !ruby/object:Gem::Requirement
173
+ none: false
174
+ requirements:
175
+ - - ">="
176
+ - !ruby/object:Gem::Version
177
+ hash: 3
178
+ segments:
179
+ - 0
180
+ version: "0"
181
+ required_rubygems_version: !ruby/object:Gem::Requirement
182
+ none: false
183
+ requirements:
184
+ - - ">="
185
+ - !ruby/object:Gem::Version
186
+ hash: 3
187
+ segments:
188
+ - 0
189
+ version: "0"
190
+ requirements: []
191
+
192
+ rubyforge_project:
193
+ rubygems_version: 1.8.24
194
+ signing_key:
195
+ specification_version: 3
196
+ summary: Very simple EC2 instance starter
197
+ test_files:
198
+ - test/helper.rb
199
+ - test/test_ec2-starter.rb