internuity-awsum 0.2 → 0.3

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.
Files changed (53) hide show
  1. data/Rakefile +2 -1
  2. data/lib/awsum.rb +1 -1
  3. data/lib/ec2/address.rb +118 -0
  4. data/lib/ec2/availability_zone.rb +68 -0
  5. data/lib/ec2/keypair.rb +75 -0
  6. data/lib/ec2/region.rb +96 -0
  7. data/lib/ec2/security_group.rb +175 -0
  8. data/lib/error.rb +55 -0
  9. data/lib/net_fix.rb +100 -0
  10. data/lib/requestable.rb +2 -0
  11. data/lib/s3/bucket.rb +66 -0
  12. data/lib/s3/headers.rb +24 -0
  13. data/lib/s3/object.rb +138 -0
  14. data/lib/s3/s3.rb +219 -0
  15. data/test/fixtures/ec2/addresses.xml +10 -0
  16. data/test/fixtures/ec2/allocate_address.xml +5 -0
  17. data/test/fixtures/ec2/associate_address.xml +5 -0
  18. data/test/fixtures/ec2/authorize_ip_access.xml +5 -0
  19. data/test/fixtures/ec2/authorize_owner_group_access.xml +5 -0
  20. data/test/fixtures/ec2/authorize_owner_group_access_error.xml +2 -0
  21. data/test/fixtures/ec2/availability_zones.xml +16 -0
  22. data/test/fixtures/ec2/create_key_pair.xml +29 -0
  23. data/test/fixtures/ec2/create_security_group.xml +5 -0
  24. data/test/fixtures/ec2/delete_key_pair.xml +5 -0
  25. data/test/fixtures/ec2/delete_security_group.xml +5 -0
  26. data/test/fixtures/ec2/deregister_image.xml +5 -0
  27. data/test/fixtures/ec2/disassociate_address.xml +5 -0
  28. data/test/fixtures/ec2/internal_error.xml +2 -0
  29. data/test/fixtures/ec2/invalid_amiid_error.xml +2 -0
  30. data/test/fixtures/ec2/invalid_request_error.xml +2 -0
  31. data/test/fixtures/ec2/key_pairs.xml +10 -0
  32. data/test/fixtures/ec2/regions.xml +14 -0
  33. data/test/fixtures/ec2/register_image.xml +5 -0
  34. data/test/fixtures/ec2/release_address.xml +5 -0
  35. data/test/fixtures/ec2/revoke_ip_access.xml +5 -0
  36. data/test/fixtures/ec2/revoke_owner_group_access.xml +5 -0
  37. data/test/fixtures/ec2/security_groups.xml +159 -0
  38. data/test/fixtures/ec2/unassociated_address.xml +10 -0
  39. data/test/fixtures/s3/buckets.xml +2 -0
  40. data/test/fixtures/s3/copy_failure.xml +23 -0
  41. data/test/fixtures/s3/invalid_request_signature.xml +5 -0
  42. data/test/fixtures/s3/keys.xml +2 -0
  43. data/test/units/ec2/test_addresses.rb +60 -0
  44. data/test/units/ec2/test_keypair.rb +87 -0
  45. data/test/units/ec2/test_regions.rb +33 -0
  46. data/test/units/ec2/test_security_group.rb +105 -0
  47. data/test/units/s3/test_bucket.rb +58 -0
  48. data/test/units/s3/test_object.rb +111 -0
  49. data/test/units/s3/test_s3.rb +298 -0
  50. data/test/units/test_error.rb +101 -0
  51. data/test/units/test_requestable.rb +241 -0
  52. data/test/work_out_string_to_sign.rb +7 -0
  53. metadata +132 -43
data/Rakefile CHANGED
@@ -54,7 +54,8 @@ spec = Gem::Specification.new do |s|
54
54
  s.files = FileList["README*",
55
55
  "LICENSE",
56
56
  "Rakefile",
57
- "{lib,test}/**/*"].to_a
57
+ "{lib,test}/**/*",
58
+ "{lib,test}/*"].to_a
58
59
  s.require_path = "lib"
59
60
  s.test_files = FileList["test/**/test_*.rb"].to_a + FileList["test/fixtures/**/*.xml"].to_a
60
61
  s.rubyforge_project = "awsum"
@@ -15,7 +15,7 @@ require 's3/s3'
15
15
 
16
16
  module Awsum
17
17
 
18
- VERSION = "0.1"
18
+ VERSION = "0.3"
19
19
 
20
20
  API_VERSION = '2008-12-01'
21
21
  SIGNATURE_VERSION = 2
@@ -0,0 +1,118 @@
1
+ module Awsum
2
+ class Ec2
3
+ class Address
4
+ attr_reader :public_ip, :instance_id
5
+
6
+ def initialize(ec2, public_ip, instance_id) #:nodoc:
7
+ @ec2 = ec2
8
+ @public_ip = public_ip
9
+ @instance_id = instance_id
10
+ end
11
+
12
+ # Get the Instance associated with this address.
13
+ #
14
+ # Returns nil if no instance is associated.
15
+ def instance
16
+ @ec2.instance(@instance_id) if @instance_id
17
+ end
18
+
19
+ # Will associate this address with an instance
20
+ #
21
+ # Raises an error if the address is already associated with an instance
22
+ def associate(instance_id)
23
+ if @instance_id.nil?
24
+ @ec2.associate_address instance_id, @public_ip
25
+ else
26
+ raise 'Cannot associate with an already associated instance' #FIXME: Write a better Awsum error here'
27
+ end
28
+ end
29
+
30
+ # Will disassociate this address from it's instance
31
+ #
32
+ # Raises an error if the address is not associated with an instance
33
+ def disassociate
34
+ if @instance_id.nil?
35
+ raise 'Not associated' #FIXME: Write a better Awsum error here'
36
+ else
37
+ result = @ec2.disassociate_address @public_ip
38
+ @instance_id = nil
39
+ result
40
+ end
41
+ end
42
+
43
+ # Will release this address
44
+ #
45
+ # Raises an error if the address is associated with an instance
46
+ def release
47
+ if @instance_id.nil?
48
+ @ec2.release_address @public_ip
49
+ else
50
+ raise 'Associated with an instance' #FIXME: Write a better Awsum error here'
51
+ end
52
+ end
53
+
54
+ # Will release this address regardless of whether it is associated with an instance or not.
55
+ def release!
56
+ @ec2.release_address! @public_ip
57
+ end
58
+ end
59
+
60
+ class AddressParser < Awsum::Parser #:nodoc:
61
+ def initialize(ec2)
62
+ @ec2 = ec2
63
+ @addresses = []
64
+ @text = nil
65
+ @stack = []
66
+ end
67
+
68
+ def tag_start(tag, attributes)
69
+ #Quick hack so we can use the same parser for AllocateAddress which doesn't use the item tag to wrap the address information
70
+ if tag == 'AllocateAddressResponse'
71
+ @stack << 'addressesSet'
72
+ end
73
+
74
+ case tag
75
+ when 'addressesSet'
76
+ @stack << 'addressesSet'
77
+ when 'item', 'AllocateAddressResponse'
78
+ case @stack[-1]
79
+ when 'addressesSet'
80
+ @current = {}
81
+ end
82
+ end
83
+ @text = ''
84
+ end
85
+
86
+ def text(text)
87
+ @text << text unless @text.nil?
88
+ end
89
+
90
+ def tag_end(tag)
91
+ case tag
92
+ when 'DescribeAddressesResponse'
93
+ #no-op
94
+ when 'addressesSet'
95
+ @stack.pop
96
+ when 'item', 'AllocateAddressResponse'
97
+ case @stack[-1]
98
+ when 'addressesSet'
99
+ @addresses << Address.new(
100
+ @ec2,
101
+ @current['publicIp'],
102
+ @current['instanceId']
103
+ )
104
+ end
105
+ else
106
+ unless @text.nil? || @current.nil?
107
+ text = @text.strip
108
+ @current[tag] = (text == '' ? nil : text)
109
+ end
110
+ end
111
+ end
112
+
113
+ def result
114
+ @addresses
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,68 @@
1
+ module Awsum
2
+ class Ec2
3
+ class AvailabilityZone
4
+ attr_reader :name, :state, :availability_zone_name
5
+
6
+ def initialize(ec2, name, state, availability_zone_name) #:nodoc:
7
+ @ec2 = ec2
8
+ @name = name
9
+ @state = state
10
+ @availability_zone_name = availability_zone_name
11
+ end
12
+ end
13
+
14
+ class AvailabilityZoneParser < Awsum::Parser #:nodoc:
15
+ def initialize(ec2)
16
+ @ec2 = ec2
17
+ @availability_zones = []
18
+ @text = nil
19
+ @stack = []
20
+ end
21
+
22
+ def tag_start(tag, attributes)
23
+ case tag
24
+ when 'availabilityZoneInfo'
25
+ @stack << 'availabilityZoneInfo'
26
+ when 'item'
27
+ case @stack[-1]
28
+ when 'availabilityZoneInfo'
29
+ @current = {}
30
+ end
31
+ end
32
+ @text = ''
33
+ end
34
+
35
+ def text(text)
36
+ @text << text unless @text.nil?
37
+ end
38
+
39
+ def tag_end(tag)
40
+ case tag
41
+ when 'DescribeAvailabilityZonesResponse', 'requestId'
42
+ #no-op
43
+ when 'availabilityZoneInfo'
44
+ @stack.pop
45
+ when 'item'
46
+ case @stack[-1]
47
+ when 'availabilityZoneInfo'
48
+ @availability_zones << AvailabilityZone.new(
49
+ @ec2,
50
+ @current['zoneName'],
51
+ @current['zoneState'],
52
+ @current['regionName']
53
+ )
54
+ end
55
+ else
56
+ unless @text.nil? || @current.nil?
57
+ text = @text.strip
58
+ @current[tag] = (text == '' ? nil : text)
59
+ end
60
+ end
61
+ end
62
+
63
+ def result
64
+ @availability_zones
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,75 @@
1
+ module Awsum
2
+ class Ec2
3
+ class KeyPair
4
+ attr_reader :name, :fingerprint, :material
5
+
6
+ def initialize(ec2, name, fingerprint, material)
7
+ @ec2 = ec2
8
+ @name = name
9
+ @fingerprint = fingerprint
10
+ @material = material
11
+ end
12
+ end
13
+
14
+ class KeyPairParser < Awsum::Parser #:nodoc:
15
+ def initialize(ec2)
16
+ @ec2 = ec2
17
+ @key_pairs = []
18
+ @text = nil
19
+ @stack = []
20
+ end
21
+
22
+ def tag_start(tag, attributes)
23
+ #Quick hack so we can use the same parser for CreateKeyPair which doesn't use the item tag to wrap the key pair information
24
+ if tag == 'CreateKeyPairResponse'
25
+ @stack << 'keySet'
26
+ end
27
+
28
+ case tag
29
+ when 'keySet'
30
+ @stack << 'keySet'
31
+ when 'item', 'CreateKeyPairResponse'
32
+ case @stack[-1]
33
+ when 'keySet'
34
+ @current = {}
35
+ @text = ''
36
+ end
37
+ end
38
+ end
39
+
40
+ def text(text)
41
+ @text << text unless @text.nil?
42
+ end
43
+
44
+ def tag_end(tag)
45
+ case tag
46
+ when 'DescribeKeyPairsResponse'
47
+ #no-op
48
+ when 'keySet'
49
+ @stack.pop
50
+ when 'item', 'CreateKeyPairResponse'
51
+ case @stack[-1]
52
+ when 'keySet'
53
+ @key_pairs << KeyPair.new(
54
+ @ec2,
55
+ @current['keyName'],
56
+ @current['keyFingerprint'],
57
+ @current['keyMaterial']
58
+ )
59
+ @text = ''
60
+ end
61
+ else
62
+ unless @text.nil?
63
+ text = @text.strip
64
+ @current[tag] = (text == '' ? nil : text)
65
+ @text = ''
66
+ end
67
+ end
68
+ end
69
+
70
+ def result
71
+ @key_pairs
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,96 @@
1
+ module Awsum
2
+ class Ec2
3
+ class Region
4
+ attr_reader :name, :end_point
5
+
6
+ def initialize(ec2, name, end_point) #:nodoc:
7
+ @ec2 = ec2
8
+ @name = name
9
+ @end_point = end_point
10
+ end
11
+
12
+ # List the AvailabilityZone(s) of this Region
13
+ def availability_zones
14
+ @ec2.availability_zones
15
+ end
16
+
17
+ # Operate all Awsum::Ec2 methods against this Region
18
+ #
19
+ # ====Example
20
+ #
21
+ # ec2.region('eu-west-1').use do
22
+ # #Runs an instance within the eu-west-1 region
23
+ # instance = run_instances('i-ABCDEF')
24
+ # end
25
+ def use(&block)
26
+ old_host = @ec2.host
27
+ @ec2.host = end_point
28
+ if block
29
+ block.arity < 1 ? instance_eval(&block) : block[self]
30
+ end
31
+ @ec2.host = old_host
32
+ self
33
+ end
34
+
35
+ private
36
+ #--
37
+ # Will pass all missing methods onto the ec2 object
38
+ def method_missing(method_name, *args, &block)
39
+ @ec2.send(method_name, *args, &block)
40
+ end
41
+ end
42
+
43
+ class RegionParser < Awsum::Parser #:nodoc:
44
+ def initialize(ec2)
45
+ @ec2 = ec2
46
+ @regions = []
47
+ @text = nil
48
+ @stack = []
49
+ end
50
+
51
+ def tag_start(tag, attributes)
52
+ case tag
53
+ when 'regionInfo'
54
+ @stack << 'regionInfo'
55
+ when 'item'
56
+ case @stack[-1]
57
+ when 'regionInfo'
58
+ @current = {}
59
+ end
60
+ end
61
+ @text = ''
62
+ end
63
+
64
+ def text(text)
65
+ @text << text unless @text.nil?
66
+ end
67
+
68
+ def tag_end(tag)
69
+ case tag
70
+ when 'DescribeRegionsResponse', 'requestId'
71
+ #no-op
72
+ when 'regionInfo'
73
+ @stack.pop
74
+ when 'item'
75
+ case @stack[-1]
76
+ when 'regionInfo'
77
+ @regions << Region.new(
78
+ @ec2,
79
+ @current['regionName'],
80
+ @current['regionEndpoint']
81
+ )
82
+ end
83
+ else
84
+ unless @text.nil? || @current.nil?
85
+ text = @text.strip
86
+ @current[tag] = (text == '' ? nil : text)
87
+ end
88
+ end
89
+ end
90
+
91
+ def result
92
+ @regions
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,175 @@
1
+ module Awsum
2
+ class Ec2
3
+ class SecurityGroup
4
+ attr_reader :name, :description, :owner_id, :ip_permissions, :group_permissions
5
+
6
+ def initialize(ec2, name, description, owner_id, ip_permissions, group_permissions)
7
+ @ec2 = ec2
8
+ @name = name
9
+ @description = description
10
+ @owner_id = owner_id
11
+ @ip_permissions = ip_permissions
12
+ @group_permissions = group_permissions
13
+ end
14
+
15
+ # Authorize access for a group
16
+ def authorize_group(group_name, owner_id)
17
+ @ec2.authorize_security_group_ingress(@name, :source_security_group_name => group_name, :source_security_group_owner_id => owner_id)
18
+ end
19
+
20
+ # Revoke access for a group
21
+ def revoke_group(group_name, owner_id)
22
+ @ec2.revoke_security_group_ingress(@name, :source_security_group_name => group_name, :source_security_group_owner_id => owner_id)
23
+ end
24
+
25
+ # Authorize access for an ip address
26
+ def authorize_ip(from_port, to_port, protocol = 'tcp', cidr_ip = '0.0.0.0/0')
27
+ @ec2.authorize_security_group_ingress(@name, :ip_protocol => protocol, :from_port => from_port, :to_port => to_port, :cidr_ip => cidr_ip)
28
+ end
29
+
30
+ # Revoke access from an ip address
31
+ def revoke_ip(from_port, to_port, protocol = 'tcp', cidr_ip = '0.0.0.0/0')
32
+ @ec2.revoke_security_group_ingress(@name, :ip_protocol => protocol, :from_port => from_port, :to_port => to_port, :cidr_ip => cidr_ip)
33
+ end
34
+
35
+ # Delete this SecurityGroup
36
+ def delete
37
+ @ec2.delete_security_group(@name)
38
+ end
39
+
40
+ private
41
+ class Permission #:nodoc:
42
+ attr_reader :protocol, :from_port, :to_port
43
+
44
+ def initialize(protocol, from_port, to_port)
45
+ @protocol = protocol
46
+ @from_port = from_port.to_i
47
+ @to_port = to_port.to_i
48
+ end
49
+ end
50
+
51
+ protected
52
+ class IpPermission < Permission
53
+ attr_reader :ip
54
+
55
+ def initialize(protocol, from_port, to_port, ip)
56
+ super(protocol, from_port, to_port)
57
+ @ip = ip
58
+ end
59
+ end
60
+
61
+ class GroupPermission < Permission
62
+ attr_reader :group, :user_id
63
+
64
+ def initialize(protocol, from_port, to_port, group, user_id)
65
+ super(protocol, from_port, to_port)
66
+ @group = group
67
+ @user_id = user_id
68
+ end
69
+ end
70
+ end
71
+
72
+ class SecurityGroupParser < Awsum::Parser #:nodoc:
73
+ def initialize(ec2)
74
+ @ec2 = ec2
75
+ @security_groups = []
76
+ @text = nil
77
+ @stack = []
78
+ @group_permissions = []
79
+ @ip_permissions = []
80
+ end
81
+
82
+ def tag_start(tag, attributes)
83
+ case tag
84
+ when 'securityGroupInfo'
85
+ @stack << 'securityGroupInfo'
86
+ when 'ipPermissions'
87
+ @stack << 'ipPermissions'
88
+ when 'groups'
89
+ @stack << 'groups'
90
+ when 'ipRanges'
91
+ @stack << 'ipRanges'
92
+ when 'item'
93
+ case @stack[-1]
94
+ when 'securityGroupInfo'
95
+ @current = {}
96
+ @group_permissions = []
97
+ @ip_permissions = []
98
+ @text = ''
99
+ when 'ipPermissions'
100
+ @permissions = {}
101
+ @text = ''
102
+ when 'groups'
103
+ @group_info = {}
104
+ @text = ''
105
+ when 'ipRanges'
106
+ @ip_info = {}
107
+ @text = ''
108
+ end
109
+ end
110
+ end
111
+
112
+ def text(text)
113
+ @text << text unless @text.nil?
114
+ end
115
+
116
+ def tag_end(tag)
117
+ case tag
118
+ when 'DescribeSecurityGroupsResponse', 'requestId'
119
+ #no-op
120
+ when 'securityGroupInfo', 'ipPermissions', 'groups', 'ipRanges'
121
+ @stack.pop
122
+ when 'item'
123
+ case @stack[-1]
124
+ when 'securityGroupInfo'
125
+ @security_groups << SecurityGroup.new(
126
+ @ec2,
127
+ @current['groupName'],
128
+ @current['groupDescription'],
129
+ @current['ownerId'],
130
+ @ip_permissions,
131
+ @group_permissions
132
+ )
133
+ @text = ''
134
+ when 'groups'
135
+ @group_permissions << SecurityGroup::GroupPermission.new(
136
+ @permissions['ipProtocol'],
137
+ @permissions['fromPort'],
138
+ @permissions['toPort'],
139
+ @group_info['groupName'],
140
+ @group_info['userId']
141
+ )
142
+ when 'ipRanges'
143
+ @ip_permissions << SecurityGroup::IpPermission.new(
144
+ @permissions['ipProtocol'],
145
+ @permissions['fromPort'],
146
+ @permissions['toPort'],
147
+ @ip_info['cidrIp']
148
+ )
149
+ end
150
+ else
151
+ unless @text.nil?
152
+ text = @text.strip
153
+ text = (text == '' ? nil : text)
154
+
155
+ case @stack[-1]
156
+ when 'securityGroupInfo'
157
+ @current[tag] = text
158
+ when 'ipPermissions'
159
+ @permissions[tag] = text
160
+ when 'groups'
161
+ @group_info[tag] = text
162
+ when 'ipRanges'
163
+ @ip_info[tag] = text
164
+ end
165
+ @text = ''
166
+ end
167
+ end
168
+ end
169
+
170
+ def result
171
+ @security_groups
172
+ end
173
+ end
174
+ end
175
+ end