awsum 0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/.autotest +1 -0
- data/.gitignore +5 -0
- data/.rspec +1 -0
- data/Gemfile +15 -0
- data/Gemfile.lock +44 -0
- data/LICENSE +19 -0
- data/README.rdoc +42 -0
- data/Rakefile +75 -0
- data/awsum.gemspec +199 -0
- data/lib/awsum.rb +20 -0
- data/lib/awsum/ec2.rb +741 -0
- data/lib/awsum/ec2/address.rb +67 -0
- data/lib/awsum/ec2/availability_zone.rb +16 -0
- data/lib/awsum/ec2/image.rb +62 -0
- data/lib/awsum/ec2/instance.rb +57 -0
- data/lib/awsum/ec2/keypair.rb +16 -0
- data/lib/awsum/ec2/parsers/address_parser.rb +61 -0
- data/lib/awsum/ec2/parsers/availability_zone_parser.rb +57 -0
- data/lib/awsum/ec2/parsers/image_parser.rb +74 -0
- data/lib/awsum/ec2/parsers/instance_parser.rb +90 -0
- data/lib/awsum/ec2/parsers/keypair_parser.rb +64 -0
- data/lib/awsum/ec2/parsers/purchase_reserved_instances_offering_parser.rb +34 -0
- data/lib/awsum/ec2/parsers/region_parser.rb +56 -0
- data/lib/awsum/ec2/parsers/register_image_parser.rb +34 -0
- data/lib/awsum/ec2/parsers/reserved_instance_parser.rb +64 -0
- data/lib/awsum/ec2/parsers/reserved_instances_offering_parser.rb +63 -0
- data/lib/awsum/ec2/parsers/security_group_parser.rb +106 -0
- data/lib/awsum/ec2/parsers/snapshot_parser.rb +64 -0
- data/lib/awsum/ec2/parsers/volume_parser.rb +77 -0
- data/lib/awsum/ec2/region.rb +54 -0
- data/lib/awsum/ec2/reserved_instance.rb +24 -0
- data/lib/awsum/ec2/reserved_instances_offering.rb +20 -0
- data/lib/awsum/ec2/security_group.rb +74 -0
- data/lib/awsum/ec2/snapshot.rb +23 -0
- data/lib/awsum/ec2/volume.rb +65 -0
- data/lib/awsum/error.rb +53 -0
- data/lib/awsum/net_fix.rb +100 -0
- data/lib/awsum/parser.rb +18 -0
- data/lib/awsum/requestable.rb +216 -0
- data/lib/awsum/s3.rb +220 -0
- data/lib/awsum/s3/bucket.rb +28 -0
- data/lib/awsum/s3/headers.rb +24 -0
- data/lib/awsum/s3/object.rb +138 -0
- data/lib/awsum/s3/parsers/bucket_parser.rb +43 -0
- data/lib/awsum/support.rb +94 -0
- data/spec/fixtures/ec2/addresses.xml +10 -0
- data/spec/fixtures/ec2/allocate_address.xml +5 -0
- data/spec/fixtures/ec2/associate_address.xml +5 -0
- data/spec/fixtures/ec2/attach_volume.xml +9 -0
- data/spec/fixtures/ec2/authorize_ip_access.xml +5 -0
- data/spec/fixtures/ec2/authorize_owner_group_access.xml +5 -0
- data/spec/fixtures/ec2/authorize_owner_group_access_error.xml +2 -0
- data/spec/fixtures/ec2/availability_zones.xml +16 -0
- data/spec/fixtures/ec2/available_volume.xml +14 -0
- data/spec/fixtures/ec2/create_key_pair.xml +29 -0
- data/spec/fixtures/ec2/create_security_group.xml +5 -0
- data/spec/fixtures/ec2/create_snapshot.xml +9 -0
- data/spec/fixtures/ec2/create_volume.xml +10 -0
- data/spec/fixtures/ec2/delete_key_pair.xml +5 -0
- data/spec/fixtures/ec2/delete_security_group.xml +5 -0
- data/spec/fixtures/ec2/delete_snapshot.xml +5 -0
- data/spec/fixtures/ec2/delete_volume.xml +5 -0
- data/spec/fixtures/ec2/deregister_image.xml +5 -0
- data/spec/fixtures/ec2/detach_volume.xml +9 -0
- data/spec/fixtures/ec2/disassociate_address.xml +5 -0
- data/spec/fixtures/ec2/image.xml +15 -0
- data/spec/fixtures/ec2/images.xml +77 -0
- data/spec/fixtures/ec2/instance.xml +36 -0
- data/spec/fixtures/ec2/instances.xml +88 -0
- data/spec/fixtures/ec2/internal_error.xml +2 -0
- data/spec/fixtures/ec2/invalid_amiid_error.xml +2 -0
- data/spec/fixtures/ec2/invalid_request_error.xml +2 -0
- data/spec/fixtures/ec2/key_pairs.xml +10 -0
- data/spec/fixtures/ec2/purchase_reserved_instances_offering.xml +5 -0
- data/spec/fixtures/ec2/purchase_reserved_instances_offerings.xml +6 -0
- data/spec/fixtures/ec2/regions.xml +14 -0
- data/spec/fixtures/ec2/register_image.xml +5 -0
- data/spec/fixtures/ec2/release_address.xml +5 -0
- data/spec/fixtures/ec2/reserved_instances.xml +18 -0
- data/spec/fixtures/ec2/reserved_instances_offering.xml +15 -0
- data/spec/fixtures/ec2/reserved_instances_offerings.xml +276 -0
- data/spec/fixtures/ec2/revoke_ip_access.xml +5 -0
- data/spec/fixtures/ec2/revoke_owner_group_access.xml +5 -0
- data/spec/fixtures/ec2/run_instances.xml +30 -0
- data/spec/fixtures/ec2/security_groups.xml +159 -0
- data/spec/fixtures/ec2/snapshots.xml +13 -0
- data/spec/fixtures/ec2/terminate_instances.xml +17 -0
- data/spec/fixtures/ec2/unassociated_address.xml +10 -0
- data/spec/fixtures/ec2/volumes.xml +23 -0
- data/spec/fixtures/errors/invalid_parameter_value.xml +2 -0
- data/spec/fixtures/s3/buckets.xml +2 -0
- data/spec/fixtures/s3/copy_failure.xml +23 -0
- data/spec/fixtures/s3/invalid_request_signature.xml +5 -0
- data/spec/fixtures/s3/keys.xml +2 -0
- data/spec/lib/awsum/ec2/address_spec.rb +149 -0
- data/spec/lib/awsum/ec2/availability_zones_spec.rb +21 -0
- data/spec/lib/awsum/ec2/image_spec.rb +92 -0
- data/spec/lib/awsum/ec2/instance_spec.rb +125 -0
- data/spec/lib/awsum/ec2/keypair_spec.rb +55 -0
- data/spec/lib/awsum/ec2/parsers/address_parser_spec.rb +51 -0
- data/spec/lib/awsum/ec2/parsers/availability_zone_parser_spec.rb +28 -0
- data/spec/lib/awsum/ec2/parsers/image_parser_spec.rb +66 -0
- data/spec/lib/awsum/ec2/parsers/instance_parser_spec.rb +75 -0
- data/spec/lib/awsum/ec2/parsers/keypair_parser_spec.rb +74 -0
- data/spec/lib/awsum/ec2/parsers/purchase_reserved_instances_offering_parser_spec.rb +14 -0
- data/spec/lib/awsum/ec2/parsers/region_parser_spec.rb +27 -0
- data/spec/lib/awsum/ec2/parsers/register_image_parser_spec.rb +15 -0
- data/spec/lib/awsum/ec2/parsers/reserved_instance_parser_spec.rb +35 -0
- data/spec/lib/awsum/ec2/parsers/reserved_instances_offering_parser_spec.rb +32 -0
- data/spec/lib/awsum/ec2/parsers/security_group_parser_spec.rb +78 -0
- data/spec/lib/awsum/ec2/parsers/snapshot_parser_spec.rb +30 -0
- data/spec/lib/awsum/ec2/parsers/volume_parser_spec.rb +35 -0
- data/spec/lib/awsum/ec2/region_spec.rb +73 -0
- data/spec/lib/awsum/ec2/reserved_instance_spec.rb +61 -0
- data/spec/lib/awsum/ec2/reserved_instances_offering_spec.rb +33 -0
- data/spec/lib/awsum/ec2/security_group_spec.rb +179 -0
- data/spec/lib/awsum/ec2/snapshots_spec.rb +69 -0
- data/spec/lib/awsum/ec2/volume_spec.rb +107 -0
- data/spec/lib/awsum/ec2_spec.rb +6 -0
- data/spec/lib/awsum/error_spec.rb +31 -0
- data/spec/lib/awsum/requestable_spec.rb +126 -0
- data/spec/lib/awsum/s3/bucket_spec.rb +95 -0
- data/spec/lib/awsum/s3/object_spec.rb +128 -0
- data/spec/lib/awsum/s3/parsers/bucket_parser_spec.rb +41 -0
- data/spec/lib/awsum/s3/parsers/object_parser_spec.rb +41 -0
- data/spec/spec_helper.rb +16 -0
- metadata +240 -0
data/.autotest
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'autotest/redgreen'
|
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
diff-lcs (1.1.2)
|
5
|
+
fakeweb (1.2.8)
|
6
|
+
gemcutter (0.6.1)
|
7
|
+
git (1.2.5)
|
8
|
+
jeweler (1.4.0)
|
9
|
+
gemcutter (>= 0.1.0)
|
10
|
+
git (>= 1.2.5)
|
11
|
+
rubyforge (>= 2.0.0)
|
12
|
+
json_pure (1.4.6)
|
13
|
+
mocha (0.9.8)
|
14
|
+
rake
|
15
|
+
rake (0.8.7)
|
16
|
+
rcov (0.9.9)
|
17
|
+
rspec (2.0.0.beta.22)
|
18
|
+
rspec-core (= 2.0.0.beta.22)
|
19
|
+
rspec-expectations (= 2.0.0.beta.22)
|
20
|
+
rspec-mocks (= 2.0.0.beta.22)
|
21
|
+
rspec-core (2.0.0.beta.22)
|
22
|
+
rspec-expectations (2.0.0.beta.22)
|
23
|
+
diff-lcs (>= 1.1.2)
|
24
|
+
rspec-mocks (2.0.0.beta.22)
|
25
|
+
rspec-core (= 2.0.0.beta.22)
|
26
|
+
rspec-expectations (= 2.0.0.beta.22)
|
27
|
+
rubyforge (2.0.4)
|
28
|
+
json_pure (>= 1.1.7)
|
29
|
+
shoulda (2.11.3)
|
30
|
+
timecop (0.3.5)
|
31
|
+
|
32
|
+
PLATFORMS
|
33
|
+
ruby
|
34
|
+
|
35
|
+
DEPENDENCIES
|
36
|
+
bundler (~> 1.0.0)
|
37
|
+
fakeweb
|
38
|
+
jeweler
|
39
|
+
mocha
|
40
|
+
rake
|
41
|
+
rcov
|
42
|
+
rspec (>= 2.0.0.beta.22)
|
43
|
+
shoulda
|
44
|
+
timecop
|
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2009 Internuity Ltd, Andrew Timberlake <andrew@andrewtimberlake.com>
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
=Awsum
|
2
|
+
|
3
|
+
Awsum (Pronounced Awesome) is a library for working with Amazon web services.
|
4
|
+
The concept of Awsum is to expose the AWS library is the most ruby way possible
|
5
|
+
allowing you to work with objects in a very natural way.
|
6
|
+
|
7
|
+
==Quick Start
|
8
|
+
|
9
|
+
#Create a snapshot for every volume of every instance you own
|
10
|
+
ec2 = Awsum::Ec2.new(<access key>, <secret key>)
|
11
|
+
ec2.instances.each do |instance|
|
12
|
+
instance.volumes.each do |volume|
|
13
|
+
volume.create_snapshot
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
==Working with different Regions
|
18
|
+
You can use blocks to wrap your calls for a specific Region
|
19
|
+
ec2.region('eu-west-1').use do
|
20
|
+
#Run an instance in the eu-west-1 region
|
21
|
+
run_instance(...)
|
22
|
+
end
|
23
|
+
|
24
|
+
==Using the library on an EC2 instance
|
25
|
+
|
26
|
+
There are two methods specifically for using a library on an EC2 instance
|
27
|
+
Awsum::Ec2#me
|
28
|
+
Awsum::Ec2#user_data
|
29
|
+
|
30
|
+
To extend the quick start example, you could do
|
31
|
+
|
32
|
+
#Create a snapshot of every volume of the currently running instance
|
33
|
+
ec2 = Awsum::Ec2.new(<access key>, <secret key>)
|
34
|
+
ec2.me.volumes.each do |volume|
|
35
|
+
volume.create_snapshot
|
36
|
+
end
|
37
|
+
|
38
|
+
==Note:
|
39
|
+
|
40
|
+
Awsum is currently under active development and only supports EC2 at the moment.
|
41
|
+
|
42
|
+
Once EC2 is complete, I will focus on S3, SQS, CloudSpace and then others
|
data/Rakefile
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
begin
|
3
|
+
Bundler.setup(:default, :development)
|
4
|
+
rescue Bundler::BundlerError => e
|
5
|
+
$stderr.puts e.message
|
6
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
7
|
+
exit e.status_code
|
8
|
+
end
|
9
|
+
|
10
|
+
require 'rake/rdoctask'
|
11
|
+
require 'rake/testtask'
|
12
|
+
|
13
|
+
$LOAD_PATH.unshift('lib')
|
14
|
+
require 'awsum'
|
15
|
+
|
16
|
+
begin
|
17
|
+
require 'jeweler'
|
18
|
+
|
19
|
+
Jeweler::Tasks.new do |gem|
|
20
|
+
gem.name = 'awsum'
|
21
|
+
gem.summary = 'A library for working with Amazon Web Services in the most natural rubyish way'
|
22
|
+
gem.email = 'andrew@andrewtimberlake.com'
|
23
|
+
gem.homepage = 'http://andrewtimberlake.com/projects/awsum'
|
24
|
+
gem.authors = ['Andrew Timberlake']
|
25
|
+
gem.version = Awsum::VERSION
|
26
|
+
|
27
|
+
#gem.add_dependency
|
28
|
+
gem.add_development_dependency('rspec', '>= 2.0.0.beta.22')
|
29
|
+
end
|
30
|
+
|
31
|
+
Jeweler::GemcutterTasks.new
|
32
|
+
|
33
|
+
task :default => :spec
|
34
|
+
rescue LoadError
|
35
|
+
puts "Jeweler not available. Install it with: gem install jeweler"
|
36
|
+
end
|
37
|
+
|
38
|
+
desc 'Run code coverage'
|
39
|
+
task :coverage do |t|
|
40
|
+
puts `rcov -T #{Dir.glob('test/**/test_*.rb').join(' ')}`
|
41
|
+
end
|
42
|
+
|
43
|
+
desc 'Start an IRB session with all necessary files required.'
|
44
|
+
task :shell do |t|
|
45
|
+
chdir File.dirname(__FILE__)
|
46
|
+
exec 'irb -I lib/ -I lib/awsum -r rubygems -r awsum'
|
47
|
+
end
|
48
|
+
|
49
|
+
desc 'Generate documentation.'
|
50
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
51
|
+
rdoc.rdoc_dir = 'doc'
|
52
|
+
rdoc.title = 'AWSum'
|
53
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
54
|
+
rdoc.rdoc_files.include('README*')
|
55
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
56
|
+
end
|
57
|
+
|
58
|
+
desc 'Clean up files.'
|
59
|
+
task :clean do |t|
|
60
|
+
FileUtils.rm_rf "doc"
|
61
|
+
FileUtils.rm_rf "tmp"
|
62
|
+
FileUtils.rm_rf "pkg"
|
63
|
+
end
|
64
|
+
|
65
|
+
require 'rspec/core/rake_task'
|
66
|
+
RSpec::Core::RakeTask.new do |t|
|
67
|
+
t.pattern = "./spec/lib/**/*_spec.rb"
|
68
|
+
end
|
69
|
+
|
70
|
+
namespace :spec do
|
71
|
+
desc "Run RSpec integration code examples (LIVE runs against Amazon AWS)"
|
72
|
+
RSpec::Core::RakeTask.new(:integration) do |t|
|
73
|
+
t.pattern = "./spec/functional/**/*_spec.rb"
|
74
|
+
end
|
75
|
+
end
|
data/awsum.gemspec
ADDED
@@ -0,0 +1,199 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{awsum}
|
8
|
+
s.version = "0.5"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Andrew Timberlake"]
|
12
|
+
s.date = %q{2010-09-19}
|
13
|
+
s.email = %q{andrew@andrewtimberlake.com}
|
14
|
+
s.extra_rdoc_files = [
|
15
|
+
"LICENSE",
|
16
|
+
"README.rdoc"
|
17
|
+
]
|
18
|
+
s.files = [
|
19
|
+
".autotest",
|
20
|
+
".gitignore",
|
21
|
+
".rspec",
|
22
|
+
"Gemfile",
|
23
|
+
"Gemfile.lock",
|
24
|
+
"LICENSE",
|
25
|
+
"README.rdoc",
|
26
|
+
"Rakefile",
|
27
|
+
"awsum.gemspec",
|
28
|
+
"lib/awsum.rb",
|
29
|
+
"lib/awsum/ec2.rb",
|
30
|
+
"lib/awsum/ec2/address.rb",
|
31
|
+
"lib/awsum/ec2/availability_zone.rb",
|
32
|
+
"lib/awsum/ec2/image.rb",
|
33
|
+
"lib/awsum/ec2/instance.rb",
|
34
|
+
"lib/awsum/ec2/keypair.rb",
|
35
|
+
"lib/awsum/ec2/parsers/address_parser.rb",
|
36
|
+
"lib/awsum/ec2/parsers/availability_zone_parser.rb",
|
37
|
+
"lib/awsum/ec2/parsers/image_parser.rb",
|
38
|
+
"lib/awsum/ec2/parsers/instance_parser.rb",
|
39
|
+
"lib/awsum/ec2/parsers/keypair_parser.rb",
|
40
|
+
"lib/awsum/ec2/parsers/purchase_reserved_instances_offering_parser.rb",
|
41
|
+
"lib/awsum/ec2/parsers/region_parser.rb",
|
42
|
+
"lib/awsum/ec2/parsers/register_image_parser.rb",
|
43
|
+
"lib/awsum/ec2/parsers/reserved_instance_parser.rb",
|
44
|
+
"lib/awsum/ec2/parsers/reserved_instances_offering_parser.rb",
|
45
|
+
"lib/awsum/ec2/parsers/security_group_parser.rb",
|
46
|
+
"lib/awsum/ec2/parsers/snapshot_parser.rb",
|
47
|
+
"lib/awsum/ec2/parsers/volume_parser.rb",
|
48
|
+
"lib/awsum/ec2/region.rb",
|
49
|
+
"lib/awsum/ec2/reserved_instance.rb",
|
50
|
+
"lib/awsum/ec2/reserved_instances_offering.rb",
|
51
|
+
"lib/awsum/ec2/security_group.rb",
|
52
|
+
"lib/awsum/ec2/snapshot.rb",
|
53
|
+
"lib/awsum/ec2/volume.rb",
|
54
|
+
"lib/awsum/error.rb",
|
55
|
+
"lib/awsum/net_fix.rb",
|
56
|
+
"lib/awsum/parser.rb",
|
57
|
+
"lib/awsum/requestable.rb",
|
58
|
+
"lib/awsum/s3.rb",
|
59
|
+
"lib/awsum/s3/bucket.rb",
|
60
|
+
"lib/awsum/s3/headers.rb",
|
61
|
+
"lib/awsum/s3/object.rb",
|
62
|
+
"lib/awsum/s3/parsers/bucket_parser.rb",
|
63
|
+
"lib/awsum/support.rb",
|
64
|
+
"spec/fixtures/ec2/addresses.xml",
|
65
|
+
"spec/fixtures/ec2/allocate_address.xml",
|
66
|
+
"spec/fixtures/ec2/associate_address.xml",
|
67
|
+
"spec/fixtures/ec2/attach_volume.xml",
|
68
|
+
"spec/fixtures/ec2/authorize_ip_access.xml",
|
69
|
+
"spec/fixtures/ec2/authorize_owner_group_access.xml",
|
70
|
+
"spec/fixtures/ec2/authorize_owner_group_access_error.xml",
|
71
|
+
"spec/fixtures/ec2/availability_zones.xml",
|
72
|
+
"spec/fixtures/ec2/available_volume.xml",
|
73
|
+
"spec/fixtures/ec2/create_key_pair.xml",
|
74
|
+
"spec/fixtures/ec2/create_security_group.xml",
|
75
|
+
"spec/fixtures/ec2/create_snapshot.xml",
|
76
|
+
"spec/fixtures/ec2/create_volume.xml",
|
77
|
+
"spec/fixtures/ec2/delete_key_pair.xml",
|
78
|
+
"spec/fixtures/ec2/delete_security_group.xml",
|
79
|
+
"spec/fixtures/ec2/delete_snapshot.xml",
|
80
|
+
"spec/fixtures/ec2/delete_volume.xml",
|
81
|
+
"spec/fixtures/ec2/deregister_image.xml",
|
82
|
+
"spec/fixtures/ec2/detach_volume.xml",
|
83
|
+
"spec/fixtures/ec2/disassociate_address.xml",
|
84
|
+
"spec/fixtures/ec2/image.xml",
|
85
|
+
"spec/fixtures/ec2/images.xml",
|
86
|
+
"spec/fixtures/ec2/instance.xml",
|
87
|
+
"spec/fixtures/ec2/instances.xml",
|
88
|
+
"spec/fixtures/ec2/internal_error.xml",
|
89
|
+
"spec/fixtures/ec2/invalid_amiid_error.xml",
|
90
|
+
"spec/fixtures/ec2/invalid_request_error.xml",
|
91
|
+
"spec/fixtures/ec2/key_pairs.xml",
|
92
|
+
"spec/fixtures/ec2/purchase_reserved_instances_offering.xml",
|
93
|
+
"spec/fixtures/ec2/purchase_reserved_instances_offerings.xml",
|
94
|
+
"spec/fixtures/ec2/regions.xml",
|
95
|
+
"spec/fixtures/ec2/register_image.xml",
|
96
|
+
"spec/fixtures/ec2/release_address.xml",
|
97
|
+
"spec/fixtures/ec2/reserved_instances.xml",
|
98
|
+
"spec/fixtures/ec2/reserved_instances_offering.xml",
|
99
|
+
"spec/fixtures/ec2/reserved_instances_offerings.xml",
|
100
|
+
"spec/fixtures/ec2/revoke_ip_access.xml",
|
101
|
+
"spec/fixtures/ec2/revoke_owner_group_access.xml",
|
102
|
+
"spec/fixtures/ec2/run_instances.xml",
|
103
|
+
"spec/fixtures/ec2/security_groups.xml",
|
104
|
+
"spec/fixtures/ec2/snapshots.xml",
|
105
|
+
"spec/fixtures/ec2/terminate_instances.xml",
|
106
|
+
"spec/fixtures/ec2/unassociated_address.xml",
|
107
|
+
"spec/fixtures/ec2/volumes.xml",
|
108
|
+
"spec/fixtures/errors/invalid_parameter_value.xml",
|
109
|
+
"spec/fixtures/s3/buckets.xml",
|
110
|
+
"spec/fixtures/s3/copy_failure.xml",
|
111
|
+
"spec/fixtures/s3/invalid_request_signature.xml",
|
112
|
+
"spec/fixtures/s3/keys.xml",
|
113
|
+
"spec/lib/awsum/ec2/address_spec.rb",
|
114
|
+
"spec/lib/awsum/ec2/availability_zones_spec.rb",
|
115
|
+
"spec/lib/awsum/ec2/image_spec.rb",
|
116
|
+
"spec/lib/awsum/ec2/instance_spec.rb",
|
117
|
+
"spec/lib/awsum/ec2/keypair_spec.rb",
|
118
|
+
"spec/lib/awsum/ec2/parsers/address_parser_spec.rb",
|
119
|
+
"spec/lib/awsum/ec2/parsers/availability_zone_parser_spec.rb",
|
120
|
+
"spec/lib/awsum/ec2/parsers/image_parser_spec.rb",
|
121
|
+
"spec/lib/awsum/ec2/parsers/instance_parser_spec.rb",
|
122
|
+
"spec/lib/awsum/ec2/parsers/keypair_parser_spec.rb",
|
123
|
+
"spec/lib/awsum/ec2/parsers/purchase_reserved_instances_offering_parser_spec.rb",
|
124
|
+
"spec/lib/awsum/ec2/parsers/region_parser_spec.rb",
|
125
|
+
"spec/lib/awsum/ec2/parsers/register_image_parser_spec.rb",
|
126
|
+
"spec/lib/awsum/ec2/parsers/reserved_instance_parser_spec.rb",
|
127
|
+
"spec/lib/awsum/ec2/parsers/reserved_instances_offering_parser_spec.rb",
|
128
|
+
"spec/lib/awsum/ec2/parsers/security_group_parser_spec.rb",
|
129
|
+
"spec/lib/awsum/ec2/parsers/snapshot_parser_spec.rb",
|
130
|
+
"spec/lib/awsum/ec2/parsers/volume_parser_spec.rb",
|
131
|
+
"spec/lib/awsum/ec2/region_spec.rb",
|
132
|
+
"spec/lib/awsum/ec2/reserved_instance_spec.rb",
|
133
|
+
"spec/lib/awsum/ec2/reserved_instances_offering_spec.rb",
|
134
|
+
"spec/lib/awsum/ec2/security_group_spec.rb",
|
135
|
+
"spec/lib/awsum/ec2/snapshots_spec.rb",
|
136
|
+
"spec/lib/awsum/ec2/volume_spec.rb",
|
137
|
+
"spec/lib/awsum/ec2_spec.rb",
|
138
|
+
"spec/lib/awsum/error_spec.rb",
|
139
|
+
"spec/lib/awsum/requestable_spec.rb",
|
140
|
+
"spec/lib/awsum/s3/bucket_spec.rb",
|
141
|
+
"spec/lib/awsum/s3/object_spec.rb",
|
142
|
+
"spec/lib/awsum/s3/parsers/bucket_parser_spec.rb",
|
143
|
+
"spec/lib/awsum/s3/parsers/object_parser_spec.rb",
|
144
|
+
"spec/spec_helper.rb"
|
145
|
+
]
|
146
|
+
s.homepage = %q{http://andrewtimberlake.com/projects/awsum}
|
147
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
148
|
+
s.require_paths = ["lib"]
|
149
|
+
s.rubygems_version = %q{1.3.7}
|
150
|
+
s.summary = %q{A library for working with Amazon Web Services in the most natural rubyish way}
|
151
|
+
s.test_files = [
|
152
|
+
"spec/lib/awsum/s3/parsers/object_parser_spec.rb",
|
153
|
+
"spec/lib/awsum/s3/parsers/bucket_parser_spec.rb",
|
154
|
+
"spec/lib/awsum/s3/object_spec.rb",
|
155
|
+
"spec/lib/awsum/s3/bucket_spec.rb",
|
156
|
+
"spec/lib/awsum/ec2/reserved_instance_spec.rb",
|
157
|
+
"spec/lib/awsum/ec2/region_spec.rb",
|
158
|
+
"spec/lib/awsum/ec2/availability_zones_spec.rb",
|
159
|
+
"spec/lib/awsum/ec2/parsers/register_image_parser_spec.rb",
|
160
|
+
"spec/lib/awsum/ec2/parsers/security_group_parser_spec.rb",
|
161
|
+
"spec/lib/awsum/ec2/parsers/image_parser_spec.rb",
|
162
|
+
"spec/lib/awsum/ec2/parsers/snapshot_parser_spec.rb",
|
163
|
+
"spec/lib/awsum/ec2/parsers/region_parser_spec.rb",
|
164
|
+
"spec/lib/awsum/ec2/parsers/availability_zone_parser_spec.rb",
|
165
|
+
"spec/lib/awsum/ec2/parsers/reserved_instance_parser_spec.rb",
|
166
|
+
"spec/lib/awsum/ec2/parsers/address_parser_spec.rb",
|
167
|
+
"spec/lib/awsum/ec2/parsers/purchase_reserved_instances_offering_parser_spec.rb",
|
168
|
+
"spec/lib/awsum/ec2/parsers/volume_parser_spec.rb",
|
169
|
+
"spec/lib/awsum/ec2/parsers/reserved_instances_offering_parser_spec.rb",
|
170
|
+
"spec/lib/awsum/ec2/parsers/keypair_parser_spec.rb",
|
171
|
+
"spec/lib/awsum/ec2/parsers/instance_parser_spec.rb",
|
172
|
+
"spec/lib/awsum/ec2/image_spec.rb",
|
173
|
+
"spec/lib/awsum/ec2/address_spec.rb",
|
174
|
+
"spec/lib/awsum/ec2/keypair_spec.rb",
|
175
|
+
"spec/lib/awsum/ec2/snapshots_spec.rb",
|
176
|
+
"spec/lib/awsum/ec2/volume_spec.rb",
|
177
|
+
"spec/lib/awsum/ec2/instance_spec.rb",
|
178
|
+
"spec/lib/awsum/ec2/security_group_spec.rb",
|
179
|
+
"spec/lib/awsum/ec2/reserved_instances_offering_spec.rb",
|
180
|
+
"spec/lib/awsum/ec2_spec.rb",
|
181
|
+
"spec/lib/awsum/error_spec.rb",
|
182
|
+
"spec/lib/awsum/requestable_spec.rb",
|
183
|
+
"spec/spec_helper.rb"
|
184
|
+
]
|
185
|
+
|
186
|
+
if s.respond_to? :specification_version then
|
187
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
188
|
+
s.specification_version = 3
|
189
|
+
|
190
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
191
|
+
s.add_development_dependency(%q<rspec>, [">= 2.0.0.beta.22"])
|
192
|
+
else
|
193
|
+
s.add_dependency(%q<rspec>, [">= 2.0.0.beta.22"])
|
194
|
+
end
|
195
|
+
else
|
196
|
+
s.add_dependency(%q<rspec>, [">= 2.0.0.beta.22"])
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
data/lib/awsum.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# AWSum is a library facilitating access to Amazon's web services in (hopefully)
|
2
|
+
# a very object-oriented, ruby way.
|
3
|
+
#
|
4
|
+
# Author:: Andrew Timberlake
|
5
|
+
# Copyright:: Copyright (c) 2009 Internuity Ltd
|
6
|
+
# Licence:: MIT License (http://www.opensource.org/licenses/mit-license.php)
|
7
|
+
#
|
8
|
+
|
9
|
+
require 'awsum/parser'
|
10
|
+
require 'awsum/requestable'
|
11
|
+
require 'awsum/support'
|
12
|
+
|
13
|
+
module Awsum
|
14
|
+
VERSION = "0.5"
|
15
|
+
|
16
|
+
API_VERSION = '2010-06-15'
|
17
|
+
SIGNATURE_VERSION = 2
|
18
|
+
end
|
19
|
+
|
20
|
+
|
data/lib/awsum/ec2.rb
ADDED
@@ -0,0 +1,741 @@
|
|
1
|
+
require 'awsum'
|
2
|
+
require 'awsum/ec2/address'
|
3
|
+
require 'awsum/ec2/availability_zone'
|
4
|
+
require 'awsum/ec2/image'
|
5
|
+
require 'awsum/ec2/instance'
|
6
|
+
require 'awsum/ec2/keypair'
|
7
|
+
require 'awsum/ec2/region'
|
8
|
+
require 'awsum/ec2/reserved_instance'
|
9
|
+
require 'awsum/ec2/reserved_instances_offering'
|
10
|
+
require 'awsum/ec2/security_group'
|
11
|
+
require 'awsum/ec2/snapshot'
|
12
|
+
require 'awsum/ec2/volume'
|
13
|
+
|
14
|
+
module Awsum
|
15
|
+
# Handles all interaction with Amazon EC2
|
16
|
+
#
|
17
|
+
# ==Getting Started
|
18
|
+
# Create an Awsum::Ec2 object and begin calling methods on it.
|
19
|
+
# require 'rubygems'
|
20
|
+
# require 'awsum'
|
21
|
+
# ec2 = Awsum::Ec2.new('your access id', 'your secret key')
|
22
|
+
# images = ec2.my_images
|
23
|
+
# ...
|
24
|
+
#
|
25
|
+
# All calls to EC2 can be done directly in this class, or through a more object oriented way through the various returned classes
|
26
|
+
#
|
27
|
+
# ==Examples
|
28
|
+
# ec2.image('ami-ABCDEF').run
|
29
|
+
#
|
30
|
+
# ec2.instance('i-123456789').volumes.each do |vol|
|
31
|
+
# vol.create_snapsot
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# ec2.regions.each do |region|
|
35
|
+
# region.use
|
36
|
+
# images.each do |img|
|
37
|
+
# puts "#{img.id} - #{region.name}"
|
38
|
+
# end
|
39
|
+
# end
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# ==Errors
|
43
|
+
# All methods will raise an Awsum::Error if an error is returned from Amazon
|
44
|
+
#
|
45
|
+
# ==Missing Methods
|
46
|
+
# * ConfirmProductInstance
|
47
|
+
# * ModifyImageAttribute
|
48
|
+
# * DescribeImageAttribute
|
49
|
+
# * ResetImageAttribute
|
50
|
+
# If you need any of this functionality, please consider getting involved and help complete this library.
|
51
|
+
class Ec2
|
52
|
+
include Awsum::Requestable
|
53
|
+
|
54
|
+
# Create an new ec2 instance
|
55
|
+
#
|
56
|
+
# The access_key and secret_key are both required to do any meaningful work.
|
57
|
+
#
|
58
|
+
# If you want to get these keys from environment variables, you can do that in your code as follows:
|
59
|
+
# ec2 = Awsum::Ec2.new(ENV['AWS_ACCESS_KEY_ID'], ENV['AWS_SECRET_ACCESS_KEY'])
|
60
|
+
def initialize(access_key = nil, secret_key = nil)
|
61
|
+
@access_key = access_key
|
62
|
+
@secret_key = secret_key
|
63
|
+
end
|
64
|
+
|
65
|
+
# Retrieve a list of available Images
|
66
|
+
#
|
67
|
+
# ===Options:
|
68
|
+
# * <tt>:image_ids</tt> - array of Image id's, default: []
|
69
|
+
# * <tt>:owners</tt> - array of owner id's, default: []
|
70
|
+
# * <tt>:executable_by</tt> - array of user id's who have executable permission, default: []
|
71
|
+
def images(options = {})
|
72
|
+
options = {:image_ids => [], :owners => [], :executable_by => []}.merge(options)
|
73
|
+
action = 'DescribeImages'
|
74
|
+
params = {
|
75
|
+
'Action' => action
|
76
|
+
}
|
77
|
+
#Add options
|
78
|
+
params.merge!(array_to_params(options[:image_ids], "ImageId"))
|
79
|
+
params.merge!(array_to_params(options[:owners], "Owner"))
|
80
|
+
params.merge!(array_to_params(options[:executable_by], "ExecutableBy"))
|
81
|
+
|
82
|
+
response = send_query_request(params)
|
83
|
+
parser = Awsum::Ec2::ImageParser.new(self)
|
84
|
+
parser.parse(response.body)
|
85
|
+
end
|
86
|
+
|
87
|
+
# Retrieve all Image(s) owned by you
|
88
|
+
def my_images
|
89
|
+
images :owners => 'self'
|
90
|
+
end
|
91
|
+
|
92
|
+
# Retrieve a single Image
|
93
|
+
def image(image_id)
|
94
|
+
images(:image_ids => [image_id])[0]
|
95
|
+
end
|
96
|
+
|
97
|
+
# Register an Image
|
98
|
+
def register_image(image_location)
|
99
|
+
action = 'RegisterImage'
|
100
|
+
params = {
|
101
|
+
'Action' => action,
|
102
|
+
'ImageLocation' => image_location
|
103
|
+
}
|
104
|
+
|
105
|
+
response = send_query_request(params)
|
106
|
+
parser = Awsum::Ec2::RegisterImageParser.new(self)
|
107
|
+
parser.parse(response.body)
|
108
|
+
end
|
109
|
+
|
110
|
+
# Deregister an Image. Once deregistered, you can no longer launch the Image
|
111
|
+
def deregister_image(image_id)
|
112
|
+
action = 'DeregisterImage'
|
113
|
+
params = {
|
114
|
+
'Action' => action,
|
115
|
+
'ImageId' => image_id
|
116
|
+
}
|
117
|
+
|
118
|
+
response = send_query_request(params)
|
119
|
+
response.is_a?(Net::HTTPSuccess)
|
120
|
+
end
|
121
|
+
|
122
|
+
# Launch an ec2 Instance
|
123
|
+
#
|
124
|
+
# ===Options:
|
125
|
+
# * <tt>:min</tt> - The minimum number of instances to launch. Default: 1
|
126
|
+
# * <tt>:max</tt> - The maximum number of instances to launch. Default: 1
|
127
|
+
# * <tt>:key_name</tt> - The name of the key pair with which to launch instances
|
128
|
+
# * <tt>:security_groups</tt> - The names of security groups to associate launched instances with
|
129
|
+
# * <tt>:user_data</tt> - User data made available to instances (Note: Must be 16K or less, will be base64 encoded by Awsum)
|
130
|
+
# * <tt>:instance_type</tt> - The size of the instances to launch, can be one of [m1.small, m1.large, m1.xlarge, c1.medium, c1.xlarge], default is m1.small
|
131
|
+
# * <tt>:availability_zone</tt> - The name of the availability zone to launch this Instance in
|
132
|
+
# * <tt>:kernel_id</tt> - The ID of the kernel with which to launch instances
|
133
|
+
# * <tt>:ramdisk_id</tt> - The ID of the RAM disk with which to launch instances
|
134
|
+
# * <tt>:block_device_map</tt> - A 'hash' of mappings. E.g. {'instancestore0' => 'sdb'}
|
135
|
+
def run_instances(image_id, options = {})
|
136
|
+
options = {:min => 1, :max => 1}.merge(options)
|
137
|
+
action = 'RunInstances'
|
138
|
+
params = {
|
139
|
+
'Action' => action,
|
140
|
+
'ImageId' => image_id,
|
141
|
+
'MinCount' => options[:min],
|
142
|
+
'MaxCount' => options[:max],
|
143
|
+
'KeyName' => options[:key_name],
|
144
|
+
'UserData' => options[:user_data].nil? ? nil : Base64::encode64(options[:user_data]).gsub(/\n/, ''),
|
145
|
+
'InstanceType' => options[:instance_type],
|
146
|
+
'Placement.AvailabilityZone' => options[:availability_zone],
|
147
|
+
'KernelId' => options[:kernel_id],
|
148
|
+
'RamdiskId' => options[:ramdisk_id]
|
149
|
+
}
|
150
|
+
if options[:block_device_map].respond_to?(:keys)
|
151
|
+
map = options[:block_device_map]
|
152
|
+
map.keys.each_with_index do |key, i|
|
153
|
+
params["BlockDeviceMapping.#{i+1}.VirtualName"] = key
|
154
|
+
params["BlockDeviceMapping.#{i+1}.DeviceName"] = map[key]
|
155
|
+
end
|
156
|
+
else
|
157
|
+
raise ArgumentError.new("options[:block_device_map] - must be a key => value map") unless options[:block_device_map].nil?
|
158
|
+
end
|
159
|
+
params.merge!(array_to_params(options[:security_groups], "SecurityGroup"))
|
160
|
+
|
161
|
+
response = send_query_request(params)
|
162
|
+
parser = Awsum::Ec2::InstanceParser.new(self)
|
163
|
+
parser.parse(response.body)
|
164
|
+
end
|
165
|
+
alias_method :launch_instances, :run_instances
|
166
|
+
|
167
|
+
#Retrieve the information on a number of Instance(s)
|
168
|
+
def instances(*instance_ids)
|
169
|
+
action = 'DescribeInstances'
|
170
|
+
params = {
|
171
|
+
'Action' => action
|
172
|
+
}
|
173
|
+
params.merge!(array_to_params(instance_ids, 'InstanceId'))
|
174
|
+
|
175
|
+
response = send_query_request(params)
|
176
|
+
parser = Awsum::Ec2::InstanceParser.new(self)
|
177
|
+
parser.parse(response.body)
|
178
|
+
end
|
179
|
+
|
180
|
+
#Retrieve the information on a single Instance
|
181
|
+
def instance(instance_id)
|
182
|
+
instances([instance_id])[0]
|
183
|
+
end
|
184
|
+
|
185
|
+
# Retrieves the currently running Instance
|
186
|
+
# This should only be run on a running EC2 instance
|
187
|
+
def me
|
188
|
+
require 'open-uri'
|
189
|
+
begin
|
190
|
+
instance_id = open('http://169.254.169.254/latest/meta-data/instance-id').read
|
191
|
+
instance instance_id
|
192
|
+
rescue OpenURI::HTTPError => e
|
193
|
+
nil
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
# Retreives the user-data supplied when starting the currently running Instance
|
198
|
+
# This should only be run on a running EC2 instance
|
199
|
+
def user_data
|
200
|
+
require 'open-uri'
|
201
|
+
begin
|
202
|
+
open('http://169.254.169.254/latest/user-data').read
|
203
|
+
rescue OpenURI::HTTPError => e
|
204
|
+
nil
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
# Terminates the Instance(s)
|
209
|
+
#
|
210
|
+
# Returns true if the terminations succeeds, false otherwise
|
211
|
+
def terminate_instances(*instance_ids)
|
212
|
+
action = 'TerminateInstances'
|
213
|
+
params = {
|
214
|
+
'Action' => action
|
215
|
+
}
|
216
|
+
params.merge!(array_to_params(instance_ids, 'InstanceId'))
|
217
|
+
|
218
|
+
response = send_query_request(params)
|
219
|
+
response.is_a?(Net::HTTPSuccess)
|
220
|
+
end
|
221
|
+
|
222
|
+
#Retrieve the information on a number of Volume(s)
|
223
|
+
def volumes(*volume_ids)
|
224
|
+
action = 'DescribeVolumes'
|
225
|
+
params = {
|
226
|
+
'Action' => action
|
227
|
+
}
|
228
|
+
params.merge!(array_to_params(volume_ids, 'VolumeId'))
|
229
|
+
|
230
|
+
response = send_query_request(params)
|
231
|
+
parser = Awsum::Ec2::VolumeParser.new(self)
|
232
|
+
parser.parse(response.body)
|
233
|
+
end
|
234
|
+
|
235
|
+
# Retreive information on a Volume
|
236
|
+
def volume(volume_id)
|
237
|
+
volumes(volume_id)[0]
|
238
|
+
end
|
239
|
+
|
240
|
+
# Create a new volume
|
241
|
+
#
|
242
|
+
# ===Options:
|
243
|
+
# * <tt>:size</tt> - The size of the volume to be created (in GB) (<b>NOTE:</b> Required if you are not creating from a snapshot)
|
244
|
+
# * <tt>:snapshot_id</tt> - The snapshot id from which to create the volume
|
245
|
+
#
|
246
|
+
def create_volume(availability_zone, options = {})
|
247
|
+
raise ArgumentError.new('You must specify a size if not creating a volume from a snapshot') if options[:snapshot_id].blank? && options[:size].blank?
|
248
|
+
|
249
|
+
action = 'CreateVolume'
|
250
|
+
params = {
|
251
|
+
'Action' => action,
|
252
|
+
'AvailabilityZone' => availability_zone
|
253
|
+
}
|
254
|
+
params['Size'] = options[:size] unless options[:size].blank?
|
255
|
+
params['SnapshotId'] = options[:snapshot_id] unless options[:snapshot_id].blank?
|
256
|
+
|
257
|
+
response = send_query_request(params)
|
258
|
+
parser = Awsum::Ec2::VolumeParser.new(self)
|
259
|
+
parser.parse(response.body)[0]
|
260
|
+
end
|
261
|
+
|
262
|
+
# Attach a volume to an instance
|
263
|
+
def attach_volume(volume_id, instance_id, device = '/dev/sdh')
|
264
|
+
action = 'AttachVolume'
|
265
|
+
params = {
|
266
|
+
'Action' => action,
|
267
|
+
'VolumeId' => volume_id,
|
268
|
+
'InstanceId' => instance_id,
|
269
|
+
'Device' => device
|
270
|
+
}
|
271
|
+
|
272
|
+
response = send_query_request(params)
|
273
|
+
response.is_a?(Net::HTTPSuccess)
|
274
|
+
end
|
275
|
+
|
276
|
+
# Detach a volume from an instance
|
277
|
+
#
|
278
|
+
# ===Options
|
279
|
+
# * <tt>:instance_id</tt> - The ID of the instance from which the volume will detach
|
280
|
+
# * <tt>:device</tt> - The device name
|
281
|
+
# * <tt>:force</tt> - Whether to force the detachment. <b>NOTE:</b> If forced you may have data corruption issues.
|
282
|
+
def detach_volume(volume_id, options = {})
|
283
|
+
action = 'DetachVolume'
|
284
|
+
params = {
|
285
|
+
'Action' => action,
|
286
|
+
'VolumeId' => volume_id
|
287
|
+
}
|
288
|
+
params['InstanceId'] = options[:instance_id] unless options[:instance_id].blank?
|
289
|
+
params['Device'] = options[:device] unless options[:device].blank?
|
290
|
+
params['Force'] = options[:force] unless options[:force].blank?
|
291
|
+
|
292
|
+
response = send_query_request(params)
|
293
|
+
response.is_a?(Net::HTTPSuccess)
|
294
|
+
end
|
295
|
+
|
296
|
+
# Delete a volume
|
297
|
+
def delete_volume(volume_id)
|
298
|
+
action = 'DeleteVolume'
|
299
|
+
params = {
|
300
|
+
'Action' => action,
|
301
|
+
'VolumeId' => volume_id
|
302
|
+
}
|
303
|
+
|
304
|
+
response = send_query_request(params)
|
305
|
+
response.is_a?(Net::HTTPSuccess)
|
306
|
+
end
|
307
|
+
|
308
|
+
# Create a Snapshot of a Volume
|
309
|
+
def create_snapshot(volume_id)
|
310
|
+
action = 'CreateSnapshot'
|
311
|
+
params = {
|
312
|
+
'Action' => action,
|
313
|
+
'VolumeId' => volume_id
|
314
|
+
}
|
315
|
+
|
316
|
+
response = send_query_request(params)
|
317
|
+
parser = Awsum::Ec2::SnapshotParser.new(self)
|
318
|
+
parser.parse(response.body)[0]
|
319
|
+
end
|
320
|
+
|
321
|
+
# List Snapshot(s)
|
322
|
+
def snapshots(*snapshot_ids)
|
323
|
+
action = 'DescribeSnapshots'
|
324
|
+
params = {
|
325
|
+
'Action' => action
|
326
|
+
}
|
327
|
+
params.merge!(array_to_params(snapshot_ids, 'SnapshotId'))
|
328
|
+
|
329
|
+
response = send_query_request(params)
|
330
|
+
parser = Awsum::Ec2::SnapshotParser.new(self)
|
331
|
+
parser.parse(response.body)
|
332
|
+
end
|
333
|
+
|
334
|
+
# Get the information about a Snapshot
|
335
|
+
def snapshot(snapshot_id)
|
336
|
+
snapshots(snapshot_id)[0]
|
337
|
+
end
|
338
|
+
|
339
|
+
# Delete a Snapshot
|
340
|
+
def delete_snapshot(snapshot_id)
|
341
|
+
action = 'DeleteSnapshot'
|
342
|
+
params = {
|
343
|
+
'Action' => action,
|
344
|
+
'SnapshotId' => snapshot_id
|
345
|
+
}
|
346
|
+
|
347
|
+
response = send_query_request(params)
|
348
|
+
response.is_a?(Net::HTTPSuccess)
|
349
|
+
end
|
350
|
+
|
351
|
+
# List all AvailabilityZone(s)
|
352
|
+
def availability_zones(*zone_names)
|
353
|
+
action = 'DescribeAvailabilityZones'
|
354
|
+
params = {
|
355
|
+
'Action' => action
|
356
|
+
}
|
357
|
+
params.merge!(array_to_params(zone_names, 'ZoneName'))
|
358
|
+
|
359
|
+
response = send_query_request(params)
|
360
|
+
parser = Awsum::Ec2::AvailabilityZoneParser.new(self)
|
361
|
+
parser.parse(response.body)
|
362
|
+
end
|
363
|
+
|
364
|
+
# List all Region(s)
|
365
|
+
def regions(*region_names)
|
366
|
+
action = 'DescribeRegions'
|
367
|
+
params = {
|
368
|
+
'Action' => action
|
369
|
+
}
|
370
|
+
params.merge!(array_to_params(region_names, 'RegionName'))
|
371
|
+
|
372
|
+
response = send_query_request(params)
|
373
|
+
parser = Awsum::Ec2::RegionParser.new(self)
|
374
|
+
parser.parse(response.body)
|
375
|
+
end
|
376
|
+
|
377
|
+
# List a Region
|
378
|
+
def region(region_name, &block)
|
379
|
+
region = regions(region_name)[0]
|
380
|
+
if block_given?
|
381
|
+
region.use(&block)
|
382
|
+
else
|
383
|
+
region
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
# List Addresses
|
388
|
+
def addresses(*public_ips)
|
389
|
+
action = 'DescribeAddresses'
|
390
|
+
params = {
|
391
|
+
'Action' => action
|
392
|
+
}
|
393
|
+
params.merge!(array_to_params(public_ips, 'PublicIp'))
|
394
|
+
|
395
|
+
response = send_query_request(params)
|
396
|
+
parser = Awsum::Ec2::AddressParser.new(self)
|
397
|
+
parser.parse(response.body)
|
398
|
+
end
|
399
|
+
|
400
|
+
# Get the Address with a specific public ip
|
401
|
+
def address(public_ip)
|
402
|
+
addresses(public_ip)[0]
|
403
|
+
end
|
404
|
+
|
405
|
+
# Allocate Address
|
406
|
+
#
|
407
|
+
# Will aquire an elastic ip address for use with your account
|
408
|
+
def allocate_address
|
409
|
+
action = 'AllocateAddress'
|
410
|
+
params = {
|
411
|
+
'Action' => action
|
412
|
+
}
|
413
|
+
|
414
|
+
response = send_query_request(params)
|
415
|
+
parser = Awsum::Ec2::AddressParser.new(self)
|
416
|
+
parser.parse(response.body)[0]
|
417
|
+
end
|
418
|
+
|
419
|
+
# Associate Address
|
420
|
+
#
|
421
|
+
# Will link an allocated elastic ip address to an Instance
|
422
|
+
#
|
423
|
+
# <b>NOTE:</b> If the ip address is already associated with another instance, it will be associated with the new instance.
|
424
|
+
#
|
425
|
+
# You can run this command more than once and it will not return an error.
|
426
|
+
def associate_address(instance_id, public_ip)
|
427
|
+
action = 'AssociateAddress'
|
428
|
+
params = {
|
429
|
+
'Action' => action,
|
430
|
+
'InstanceId' => instance_id,
|
431
|
+
'PublicIp' => public_ip
|
432
|
+
}
|
433
|
+
|
434
|
+
response = send_query_request(params)
|
435
|
+
response.is_a?(Net::HTTPSuccess)
|
436
|
+
end
|
437
|
+
|
438
|
+
# Disassociate Address
|
439
|
+
#
|
440
|
+
# Will disassociate an allocated elastic ip address from the Instance it's allocated to
|
441
|
+
#
|
442
|
+
# <b>NOTE:</b> You can run this command more than once and it will not return an error.
|
443
|
+
def disassociate_address(public_ip)
|
444
|
+
action = 'DisassociateAddress'
|
445
|
+
params = {
|
446
|
+
'Action' => action,
|
447
|
+
'PublicIp' => public_ip
|
448
|
+
}
|
449
|
+
|
450
|
+
response = send_query_request(params)
|
451
|
+
response.is_a?(Net::HTTPSuccess)
|
452
|
+
end
|
453
|
+
|
454
|
+
# Releases an associated Address
|
455
|
+
#
|
456
|
+
# <b>NOTE:</b> This is not a direct call to the Amazon web service. This is a safe operation that will first check to see if the address is allocated to an instance and fail if it is
|
457
|
+
# To ensure an address is released whether associated or not, use #release_address!
|
458
|
+
def release_address(public_ip)
|
459
|
+
address = address(public_ip)
|
460
|
+
|
461
|
+
if address.instance_id.nil?
|
462
|
+
action = 'ReleaseAddress'
|
463
|
+
params = {
|
464
|
+
'Action' => action,
|
465
|
+
'PublicIp' => public_ip
|
466
|
+
}
|
467
|
+
|
468
|
+
response = send_query_request(params)
|
469
|
+
response.is_a?(Net::HTTPSuccess)
|
470
|
+
else
|
471
|
+
raise 'Address is currently allocated' #FIXME: Add a proper Awsum error here
|
472
|
+
end
|
473
|
+
end
|
474
|
+
|
475
|
+
# Releases an associated Address
|
476
|
+
#
|
477
|
+
# <b>NOTE:</b> This will disassociate an address automatically if it is associated with an instance
|
478
|
+
def release_address!(public_ip)
|
479
|
+
action = 'ReleaseAddress'
|
480
|
+
params = {
|
481
|
+
'Action' => action,
|
482
|
+
'PublicIp' => public_ip
|
483
|
+
}
|
484
|
+
|
485
|
+
response = send_query_request(params)
|
486
|
+
response.is_a?(Net::HTTPSuccess)
|
487
|
+
end
|
488
|
+
|
489
|
+
# List KeyPair(s)
|
490
|
+
def key_pairs(*key_names)
|
491
|
+
action = 'DescribeKeyPairs'
|
492
|
+
params = {
|
493
|
+
'Action' => action
|
494
|
+
}
|
495
|
+
params.merge!(array_to_params(key_names, 'KeyName'))
|
496
|
+
|
497
|
+
response = send_query_request(params)
|
498
|
+
parser = Awsum::Ec2::KeyPairParser.new(self)
|
499
|
+
parser.parse(response.body)
|
500
|
+
end
|
501
|
+
|
502
|
+
# Get a single KeyPair
|
503
|
+
def key_pair(key_name)
|
504
|
+
key_pairs(key_name)[0]
|
505
|
+
end
|
506
|
+
|
507
|
+
# Create a new KeyPair
|
508
|
+
def create_key_pair(key_name)
|
509
|
+
action = 'CreateKeyPair'
|
510
|
+
params = {
|
511
|
+
'Action' => action,
|
512
|
+
'KeyName' => key_name
|
513
|
+
}
|
514
|
+
|
515
|
+
response = send_query_request(params)
|
516
|
+
parser = Awsum::Ec2::KeyPairParser.new(self)
|
517
|
+
parser.parse(response.body)[0]
|
518
|
+
end
|
519
|
+
|
520
|
+
# Delete a KeyPair
|
521
|
+
def delete_key_pair(key_name)
|
522
|
+
action = 'DeleteKeyPair'
|
523
|
+
params = {
|
524
|
+
'Action' => action,
|
525
|
+
'KeyName' => key_name
|
526
|
+
}
|
527
|
+
|
528
|
+
response = send_query_request(params)
|
529
|
+
response.is_a?(Net::HTTPSuccess)
|
530
|
+
end
|
531
|
+
|
532
|
+
# List SecurityGroup(s)
|
533
|
+
def security_groups(*group_names)
|
534
|
+
action = 'DescribeSecurityGroups'
|
535
|
+
params = {
|
536
|
+
'Action' => action
|
537
|
+
}
|
538
|
+
params.merge!(array_to_params(group_names, 'GroupName'))
|
539
|
+
|
540
|
+
response = send_query_request(params)
|
541
|
+
parser = Awsum::Ec2::SecurityGroupParser.new(self)
|
542
|
+
parser.parse(response.body)
|
543
|
+
end
|
544
|
+
|
545
|
+
# Get a single SecurityGroup
|
546
|
+
def security_group(group_name)
|
547
|
+
security_groups(group_name)[0]
|
548
|
+
end
|
549
|
+
|
550
|
+
# Create a new SecurityGroup
|
551
|
+
def create_security_group(name, description)
|
552
|
+
action = 'CreateSecurityGroup'
|
553
|
+
params = {
|
554
|
+
'Action' => action,
|
555
|
+
'GroupName' => name,
|
556
|
+
'GroupDescription' => description
|
557
|
+
}
|
558
|
+
|
559
|
+
response = send_query_request(params)
|
560
|
+
response.is_a?(Net::HTTPSuccess)
|
561
|
+
end
|
562
|
+
|
563
|
+
# Delete a SecurityGroup
|
564
|
+
def delete_security_group(group_name)
|
565
|
+
action = 'DeleteSecurityGroup'
|
566
|
+
params = {
|
567
|
+
'Action' => action,
|
568
|
+
'GroupName' => group_name
|
569
|
+
}
|
570
|
+
|
571
|
+
response = send_query_request(params)
|
572
|
+
response.is_a?(Net::HTTPSuccess)
|
573
|
+
end
|
574
|
+
|
575
|
+
# Authorize access on a specific security group
|
576
|
+
#
|
577
|
+
# ===Options:
|
578
|
+
# ====User/Group access
|
579
|
+
# * <tt>:source_security_group_name</tt> - Name of the security group to authorize access to when operating on a user/group pair
|
580
|
+
# * <tt>:source_security_group_owner_id</tt> - Owner of the security group to authorize access to when operating on a user/group pair
|
581
|
+
# ====CIDR IP access
|
582
|
+
# * <tt>:ip_protocol</tt> - IP protocol to authorize access to when operating on a CIDR IP (tcp, udp or icmp) (default: tcp)
|
583
|
+
# * <tt>:from_port</tt> - Bottom of port range to authorize access to when operating on a CIDR IP. This contains the ICMP type if ICMP is being authorized.
|
584
|
+
# * <tt>:to_port</tt> - Top of port range to authorize access to when operating on a CIDR IP. This contains the ICMP type if ICMP is being authorized.
|
585
|
+
# * <tt>:cidr_ip</tt> - CIDR IP range to authorize access to when operating on a CIDR IP. (default: 0.0.0.0/0)
|
586
|
+
def authorize_security_group_ingress(group_name, options = {})
|
587
|
+
got_at_least_one_user_group_option = !options[:source_security_group_name].nil? || !options[:source_security_group_owner_id].nil?
|
588
|
+
got_user_group_options = !options[:source_security_group_name].nil? && !options[:source_security_group_owner_id].nil?
|
589
|
+
got_at_least_one_cidr_option = !options[:ip_protocol].nil? || !options[:from_port].nil? || !options[:to_port].nil? || !options[:cidr_ip].nil?
|
590
|
+
#Add in defaults
|
591
|
+
options = {:cidr_ip => '0.0.0.0/0'}.merge(options) if got_at_least_one_cidr_option
|
592
|
+
options = {:ip_protocol => 'tcp'}.merge(options) if got_at_least_one_cidr_option
|
593
|
+
got_cidr_options = !options[:ip_protocol].nil? && !options[:from_port].nil? && !options[:to_port].nil? && !options[:cidr_ip].nil?
|
594
|
+
raise ArgumentError.new('Can only authorize user/group or CIDR IP, not both') if got_at_least_one_user_group_option && got_at_least_one_cidr_option
|
595
|
+
raise ArgumentError.new('Need all user/group options when authorizing user/group access') if got_at_least_one_user_group_option && !got_user_group_options
|
596
|
+
raise ArgumentError.new('Need all CIDR IP options when authorizing CIDR IP access') if got_at_least_one_cidr_option && !got_cidr_options
|
597
|
+
raise ArgumentError.new('ip_protocol can only be one of tcp, udp or icmp') if got_at_least_one_cidr_option && !%w(tcp udp icmp).detect{|p| p == options[:ip_protocol] }
|
598
|
+
|
599
|
+
action = 'AuthorizeSecurityGroupIngress'
|
600
|
+
params = {
|
601
|
+
'Action' => action,
|
602
|
+
'GroupName' => group_name
|
603
|
+
}
|
604
|
+
params['SourceSecurityGroupName'] = options[:source_security_group_name] unless options[:source_security_group_name].nil?
|
605
|
+
params['SourceSecurityGroupOwnerId'] = options[:source_security_group_owner_id] unless options[:source_security_group_owner_id].nil?
|
606
|
+
params['IpProtocol'] = options[:ip_protocol] unless options[:ip_protocol].nil?
|
607
|
+
params['FromPort'] = options[:from_port] unless options[:from_port].nil?
|
608
|
+
params['ToPort'] = options[:to_port] unless options[:to_port].nil?
|
609
|
+
params['CidrIp'] = options[:cidr_ip] unless options[:cidr_ip].nil?
|
610
|
+
|
611
|
+
response = send_query_request(params)
|
612
|
+
response.is_a?(Net::HTTPSuccess)
|
613
|
+
end
|
614
|
+
|
615
|
+
# Revoke access on a specific SecurityGroup
|
616
|
+
#
|
617
|
+
# ===Options:
|
618
|
+
# ====User/Group access
|
619
|
+
# * <tt>:source_security_group_name</tt> - Name of the security group to authorize access to when operating on a user/group pair
|
620
|
+
# * <tt>:source_security_group_owner_id</tt> - Owner of the security group to authorize access to when operating on a user/group pair
|
621
|
+
# ====CIDR IP access
|
622
|
+
# * <tt>:ip_protocol</tt> - IP protocol to authorize access to when operating on a CIDR IP (tcp, udp or icmp) (default: tcp)
|
623
|
+
# * <tt>:from_port</tt> - Bottom of port range to authorize access to when operating on a CIDR IP. This contains the ICMP type if ICMP is being authorized.
|
624
|
+
# * <tt>:to_port</tt> - Top of port range to authorize access to when operating on a CIDR IP. This contains the ICMP type if ICMP is being authorized.
|
625
|
+
# * <tt>:cidr_ip</tt> - CIDR IP range to authorize access to when operating on a CIDR IP. (default: 0.0.0.0/0)
|
626
|
+
def revoke_security_group_ingress(group_name, options = {})
|
627
|
+
got_at_least_one_user_group_option = !options[:source_security_group_name].nil? || !options[:source_security_group_owner_id].nil?
|
628
|
+
got_user_group_options = !options[:source_security_group_name].nil? && !options[:source_security_group_owner_id].nil?
|
629
|
+
got_at_least_one_cidr_option = !options[:ip_protocol].nil? || !options[:from_port].nil? || !options[:to_port].nil? || !options[:cidr_ip].nil?
|
630
|
+
#Add in defaults
|
631
|
+
options = {:cidr_ip => '0.0.0.0/0'}.merge(options) if got_at_least_one_cidr_option
|
632
|
+
options = {:ip_protocol => 'tcp'}.merge(options) if got_at_least_one_cidr_option
|
633
|
+
got_cidr_options = !options[:ip_protocol].nil? && !options[:from_port].nil? && !options[:to_port].nil? && !options[:cidr_ip].nil?
|
634
|
+
raise ArgumentError.new('Can only authorize user/group or CIDR IP, not both') if got_at_least_one_user_group_option && got_at_least_one_cidr_option
|
635
|
+
raise ArgumentError.new('Need all user/group options when revoking user/group access') if got_at_least_one_user_group_option && !got_user_group_options
|
636
|
+
raise ArgumentError.new('Need all CIDR IP options when revoking CIDR IP access') if got_at_least_one_cidr_option && !got_cidr_options
|
637
|
+
raise ArgumentError.new('ip_protocol can only be one of tcp, udp or icmp') if got_at_least_one_cidr_option && !%w(tcp udp icmp).detect{|p| p == options[:ip_protocol] }
|
638
|
+
|
639
|
+
action = 'RevokeSecurityGroupIngress'
|
640
|
+
params = {
|
641
|
+
'Action' => action,
|
642
|
+
'GroupName' => group_name
|
643
|
+
}
|
644
|
+
params['SourceSecurityGroupName'] = options[:source_security_group_name] unless options[:source_security_group_name].nil?
|
645
|
+
params['SourceSecurityGroupOwnerId'] = options[:source_security_group_owner_id] unless options[:source_security_group_owner_id].nil?
|
646
|
+
params['IpProtocol'] = options[:ip_protocol] unless options[:ip_protocol].nil?
|
647
|
+
params['FromPort'] = options[:from_port] unless options[:from_port].nil?
|
648
|
+
params['ToPort'] = options[:to_port] unless options[:to_port].nil?
|
649
|
+
params['CidrIp'] = options[:cidr_ip] unless options[:cidr_ip].nil?
|
650
|
+
|
651
|
+
response = send_query_request(params)
|
652
|
+
response.is_a?(Net::HTTPSuccess)
|
653
|
+
end
|
654
|
+
|
655
|
+
# List all reserved instance offerings that are available for purchase
|
656
|
+
#
|
657
|
+
# ===Options:
|
658
|
+
# * <tt>:reserved_instances_offering_ids</tt> - Display the reserved instance offerings with the specified ids. Can be an individual id or an array of ids
|
659
|
+
# * <tt>:instance_type</tt> - Display available reserved instance offerings of the specific instance type, can be one of [m1.small, m1.large, m1.xlarge, c1.medium, c1.xlarge], default is all
|
660
|
+
# * <tt>:availability_zone</tt> - Display the reserved instance offerings within the specified availability zone
|
661
|
+
# * <tt>:product_description</tt> - Display the reserved instance offerings with the specified product description
|
662
|
+
#
|
663
|
+
# ===Example
|
664
|
+
# #To get all offerings for m1.small instances in availability zone us-east-1a
|
665
|
+
# ec2.reserved_instances_offerings(:instance_type => 'm1.small', :availability_zone => 'us-east-1a')
|
666
|
+
def reserved_instances_offerings(options = {})
|
667
|
+
action = 'DescribeReservedInstancesOfferings'
|
668
|
+
params = {
|
669
|
+
'Action' => action
|
670
|
+
}
|
671
|
+
params.merge!(array_to_params(options[:reserved_instances_offering_ids], 'ReservedInstancesOfferingId')) if options[:reserved_instances_offering_ids]
|
672
|
+
params['InstanceType'] = options[:instance_type] if options[:instance_type]
|
673
|
+
params['AvailabilityZone'] = options[:availability_zone] if options[:availability_zone]
|
674
|
+
params['ProductDescription'] = options[:product_description] if options[:product_description]
|
675
|
+
|
676
|
+
response = send_query_request(params)
|
677
|
+
parser = Awsum::Ec2::ReservedInstancesOfferingParser.new(self)
|
678
|
+
parser.parse(response.body)
|
679
|
+
end
|
680
|
+
|
681
|
+
# Get a single reserved instances offering by id
|
682
|
+
def reserved_instances_offering(id)
|
683
|
+
reserved_instances_offerings(:reserved_instances_offering_ids => id)[0]
|
684
|
+
end
|
685
|
+
|
686
|
+
# Purchase reserved instances
|
687
|
+
#
|
688
|
+
# ===Options:
|
689
|
+
# * <tt>:reserved_instances_offering_ids</tt> - A single reserved instance offering id (or an array of instance ids)
|
690
|
+
# * <tt>:instance_counts</tt> - A number of reserved instances to purchase (or an array of counts per instance in the reserved_instances_offering_ids array)
|
691
|
+
#
|
692
|
+
# ===Example
|
693
|
+
# ec2.purchase_reserved_instances_offering('reservation-123456', 1)
|
694
|
+
# or
|
695
|
+
# ec2.purchase_reserved_instances_offering(['reservation-123456', 'reservation-654321'], [1, 2])
|
696
|
+
def purchase_reserved_instances_offering(reserved_instances_offering_ids, instance_counts = 1)
|
697
|
+
action = 'PurchaseReservedInstancesOffering'
|
698
|
+
params = {
|
699
|
+
'Action' => action,
|
700
|
+
}
|
701
|
+
params.merge!(array_to_params([instance_counts].flatten, 'InstanceCount'))
|
702
|
+
params.merge!(array_to_params([reserved_instances_offering_ids].flatten, 'ReservedInstancesOfferingId'))
|
703
|
+
|
704
|
+
response = send_query_request(params)
|
705
|
+
parser = Awsum::Ec2::PurchaseReservedInstancesOfferingParser.new(self)
|
706
|
+
result = parser.parse(response.body)
|
707
|
+
if reserved_instances_offering_ids.is_a?(Array)
|
708
|
+
reserved_instances(*result)
|
709
|
+
else
|
710
|
+
reserved_instance(result)
|
711
|
+
end
|
712
|
+
end
|
713
|
+
|
714
|
+
def reserved_instances(*reserved_instances_ids)
|
715
|
+
action = 'DescribeReservedInstances'
|
716
|
+
params = {
|
717
|
+
'Action' => action
|
718
|
+
}
|
719
|
+
params.merge!(array_to_params(reserved_instances_ids, 'ReservedInstanceId'))
|
720
|
+
|
721
|
+
response = send_query_request(params)
|
722
|
+
parser = Awsum::Ec2::ReservedInstanceParser.new(self)
|
723
|
+
parser.parse(response.body)
|
724
|
+
end
|
725
|
+
|
726
|
+
# Retrieve a single reserved instance by id
|
727
|
+
def reserved_instance(reserved_instance_id)
|
728
|
+
reserved_instances(reserved_instance_id)[0]
|
729
|
+
end
|
730
|
+
|
731
|
+
#private
|
732
|
+
#The host to make all requests against
|
733
|
+
def host
|
734
|
+
@host ||= 'ec2.amazonaws.com'
|
735
|
+
end
|
736
|
+
|
737
|
+
def host=(host)
|
738
|
+
@host = host
|
739
|
+
end
|
740
|
+
end
|
741
|
+
end
|