fog-aws 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/lib/fog/aws/dns.rb +14 -1
  3. data/lib/fog/aws/iam.rb +9 -0
  4. data/lib/fog/aws/models/compute/flavors.rb +50 -0
  5. data/lib/fog/aws/models/dns/records.rb +14 -20
  6. data/lib/fog/aws/models/dns/zones.rb +1 -1
  7. data/lib/fog/aws/models/storage/file.rb +28 -3
  8. data/lib/fog/aws/models/storage/files.rb +5 -0
  9. data/lib/fog/aws/parsers/.DS_Store +0 -0
  10. data/lib/fog/aws/parsers/iam/list_managed_policies.rb +29 -0
  11. data/lib/fog/aws/parsers/iam/policy_parser.rb +57 -0
  12. data/lib/fog/aws/parsers/iam/single_policy.rb +27 -0
  13. data/lib/fog/aws/rds.rb +3 -1
  14. data/lib/fog/aws/requests/.DS_Store +0 -0
  15. data/lib/fog/aws/requests/compute/authorize_security_group_ingress.rb +67 -62
  16. data/lib/fog/aws/requests/compute/delete_security_group.rb +42 -28
  17. data/lib/fog/aws/requests/dns/change_resource_record_sets.rb +20 -20
  18. data/lib/fog/aws/requests/dns/create_hosted_zone.rb +1 -3
  19. data/lib/fog/aws/requests/dns/delete_hosted_zone.rb +5 -7
  20. data/lib/fog/aws/requests/dns/get_change.rb +11 -16
  21. data/lib/fog/aws/requests/dns/get_hosted_zone.rb +1 -3
  22. data/lib/fog/aws/requests/dns/list_resource_record_sets.rb +7 -12
  23. data/lib/fog/aws/requests/dynamodb/scan.rb +2 -1
  24. data/lib/fog/aws/requests/iam/attach_group_policy.rb +32 -0
  25. data/lib/fog/aws/requests/iam/attach_role_policy.rb +32 -0
  26. data/lib/fog/aws/requests/iam/attach_user_policy.rb +32 -0
  27. data/lib/fog/aws/requests/iam/create_policy.rb +47 -0
  28. data/lib/fog/aws/requests/iam/delete_policy.rb +30 -0
  29. data/lib/fog/aws/requests/iam/detach_group_policy.rb +32 -0
  30. data/lib/fog/aws/requests/iam/detach_role_policy.rb +32 -0
  31. data/lib/fog/aws/requests/iam/detach_user_policy.rb +32 -0
  32. data/lib/fog/aws/requests/iam/list_policies.rb +47 -0
  33. data/lib/fog/aws/requests/storage/head_object_url.rb +40 -0
  34. data/lib/fog/aws/storage.rb +1 -0
  35. data/lib/fog/aws/version.rb +1 -1
  36. data/tests/models/compute/security_group_tests.rb +11 -1
  37. data/tests/models/storage/file_tests.rb +29 -0
  38. data/tests/requests/compute/security_group_tests.rb +9 -0
  39. data/tests/requests/dns/dns_tests.rb +29 -42
  40. data/tests/requests/iam/managed_policy_tests.rb +91 -0
  41. data/tests/requests/storage/object_tests.rb +6 -0
  42. metadata +18 -2
@@ -46,53 +46,67 @@ module Fog
46
46
  if name && id
47
47
  raise Fog::Compute::AWS::Error.new("May not specify both group_name and group_id")
48
48
  end
49
+
49
50
  if id
50
51
  name = self.data[:security_groups].reject { |k,v| v['groupId'] != id } .keys.first
51
52
  end
52
53
 
54
+ unless self.data[:security_groups][name]
55
+ raise Fog::Compute::AWS::NotFound.new("The security group '#{name}' does not exist")
56
+ end
57
+
53
58
  response = Excon::Response.new
54
- if self.data[:security_groups][name]
55
59
 
56
- used_by_groups = []
57
- self.region_data.each do |access_key, key_data|
58
- key_data[:security_groups].each do |group_name, group|
59
- next if group == self.data[:security_groups][name]
60
+ used_by_groups = []
60
61
 
61
- group['ipPermissions'].each do |group_ip_permission|
62
- group_ip_permission['groups'].each do |group_group_permission|
63
- if group_group_permission['groupName'] == name &&
64
- group_group_permission['userId'] == self.data[:owner_id]
65
- used_by_groups << "#{key_data[:owner_id]}:#{group_name}"
66
- end
62
+ # ec2 authorizations
63
+ self.region_data.each do |_, key_data|
64
+ key_data[:security_groups].each do |group_name, group|
65
+ next if group == self.data[:security_groups][name]
66
+
67
+ group['ipPermissions'].each do |group_ip_permission|
68
+ group_ip_permission['groups'].each do |group_group_permission|
69
+ if group_group_permission['groupName'] == name &&
70
+ group_group_permission['userId'] == self.data[:owner_id]
71
+ used_by_groups << "#{key_data[:owner_id]}:#{group_name}"
67
72
  end
68
73
  end
69
74
  end
70
75
  end
76
+ end
71
77
 
72
- active_instances = self.data[:instances].values.select do |instance|
73
- if instance['groupSet'].include?(name) && instance['instanceState'] != "terminated"
74
- instance
78
+ # rds authorizations
79
+ Fog::AWS::RDS::Mock.data[self.region].each do |_, data|
80
+ (data[:security_groups] || []).each do |group_name, group|
81
+ (group["EC2SecurityGroups"] || []).each do |ec2_group|
82
+ if ec2_group["EC2SecurityGroupName"] == name
83
+ used_by_groups << "#{group["OwnerId"]}:#{group_name}"
84
+ end
75
85
  end
76
86
  end
87
+ end
77
88
 
78
- unless used_by_groups.empty?
79
- raise Fog::Compute::AWS::Error.new("InvalidGroup.InUse => Group #{self.data[:owner_id]}:#{name} is used by groups: #{used_by_groups.uniq.join(" ")}")
89
+ active_instances = self.data[:instances].values.select do |instance|
90
+ if instance['groupSet'].include?(name) && instance['instanceState'] != "terminated"
91
+ instance
80
92
  end
93
+ end
81
94
 
82
- if active_instances.any?
83
- raise Fog::Compute::AWS::Error.new("InUse => There are active instances using security group '#{name}'")
84
- end
95
+ unless used_by_groups.empty?
96
+ raise Fog::Compute::AWS::Error.new("InvalidGroup.InUse => Group #{self.data[:owner_id]}:#{name} is used by groups: #{used_by_groups.uniq.join(" ")}")
97
+ end
85
98
 
86
- self.data[:security_groups].delete(name)
87
- response.status = 200
88
- response.body = {
89
- 'requestId' => Fog::AWS::Mock.request_id,
90
- 'return' => true
91
- }
92
- response
93
- else
94
- raise Fog::Compute::AWS::NotFound.new("The security group '#{name}' does not exist")
99
+ if active_instances.any?
100
+ raise Fog::Compute::AWS::Error.new("InUse => There are active instances using security group '#{name}'")
95
101
  end
102
+
103
+ self.data[:security_groups].delete(name)
104
+ response.status = 200
105
+ response.body = {
106
+ 'requestId' => Fog::AWS::Mock.request_id,
107
+ 'return' => true
108
+ }
109
+ response
96
110
  end
97
111
  end
98
112
  end
@@ -155,20 +155,25 @@ module Fog
155
155
  response = Excon::Response.new
156
156
  errors = []
157
157
 
158
+
158
159
  if (zone = self.data[:zones][zone_id])
159
160
  response.status = 200
160
161
 
161
162
  change_id = Fog::AWS::Mock.change_id
162
163
  change_batch.each do |change|
164
+
165
+ change_name = change[:name]
166
+ change_name = change_name + "." unless change_name.end_with?(".")
167
+
163
168
  case change[:action]
164
169
  when "CREATE"
165
170
  if zone[:records][change[:type]].nil?
166
171
  zone[:records][change[:type]] = {}
167
172
  end
168
173
 
169
- if zone[:records][change[:type]][change[:name]].nil?
174
+ if zone[:records][change[:type]][change_name].nil?
170
175
  # raise change.to_s if change[:resource_records].nil?
171
- zone[:records][change[:type]][change[:name]] =
176
+ zone[:records][change[:type]][change_name] =
172
177
  if change[:alias_target]
173
178
  record = {
174
179
  :alias_target => change[:alias_target]
@@ -178,17 +183,17 @@ module Fog
178
183
  :ttl => change[:ttl].to_s,
179
184
  }
180
185
  end
181
- zone[:records][change[:type]][change[:name]] = {
182
- :change_id => change_id,
186
+ zone[:records][change[:type]][change_name] = {
187
+ :change_id => change_id,
183
188
  :resource_records => change[:resource_records] || [],
184
- :name => change[:name],
185
- :type => change[:type]
189
+ :name => change_name,
190
+ :type => change[:type]
186
191
  }.merge(record)
187
192
  else
188
193
  errors << "Tried to create resource record set #{change[:name]}. type #{change[:type]}, but it already exists"
189
194
  end
190
195
  when "DELETE"
191
- if zone[:records][change[:type]].nil? || zone[:records][change[:type]].delete(change[:name]).nil?
196
+ if zone[:records][change[:type]].nil? || zone[:records][change[:type]].delete(change_name).nil?
192
197
  errors << "Tried to delete resource record set #{change[:name]}. type #{change[:type]}, but it was not found"
193
198
  end
194
199
  end
@@ -196,35 +201,30 @@ module Fog
196
201
 
197
202
  if errors.empty?
198
203
  change = {
199
- :id => change_id,
200
- :status => 'PENDING',
204
+ :id => change_id,
205
+ :status => 'PENDING',
201
206
  :submitted_at => Time.now.utc.iso8601
202
207
  }
203
208
  self.data[:changes][change[:id]] = change
204
209
  response.body = {
205
- 'Id' => change[:id],
206
- 'Status' => change[:status],
210
+ 'Id' => change[:id],
211
+ 'Status' => change[:status],
207
212
  'SubmittedAt' => change[:submitted_at]
208
213
  }
209
214
  response
210
215
  else
211
- response.status = 400
212
- response.body = "<?xml version=\"1.0\"?><InvalidChangeBatch xmlns=\"https://route53.amazonaws.com/doc/2012-02-29/\"><Messages>#{errors.map {|e| "<Message>#{e}</Message>"}.join()}</Messages></InvalidChangeBatch>"
213
- raise(Excon::Errors.status_error({:expects => 200}, response))
216
+ raise Fog::DNS::AWS::Error.new("InvalidChangeBatch => #{errors.join(", ")}")
214
217
  end
215
218
  else
216
- response.status = 404
217
- response.body = "<?xml version=\"1.0\"?><Response><Errors><Error><Code>NoSuchHostedZone</Code><Message>A hosted zone with the specified hosted zone ID does not exist.</Message></Error></Errors><RequestID>#{Fog::AWS::Mock.request_id}</RequestID></Response>"
218
- raise(Excon::Errors.status_error({:expects => 200}, response))
219
+ raise Fog::DNS::AWS::NotFound.new("NoSuchHostedZone => A hosted zone with the specified hosted zone ID does not exist.")
219
220
  end
220
221
  end
221
222
  end
222
223
 
223
224
  def self.hosted_zone_for_alias_target(dns_name)
224
- k = elb_hosted_zone_mapping.keys.find do |k|
225
+ elb_hosted_zone_mapping.select { |k, _|
225
226
  dns_name =~ /\A.+\.#{k}\.elb\.amazonaws\.com\.?\z/
226
- end
227
- elb_hosted_zone_mapping[k]
227
+ }.last
228
228
  end
229
229
 
230
230
  def self.elb_hosted_zone_mapping
@@ -97,9 +97,7 @@ module Fog
97
97
  }
98
98
  response
99
99
  else
100
- response.status = 400
101
- response.body = "<?xml version=\"1.0\"?><Response><Errors><Error><Code>DelegationSetNotAvailable</Code><Message>Amazon Route 53 allows some duplication, but Amazon Route 53 has a maximum threshold of duplicated domains. This error is generated when you reach that threshold. In this case, the error indicates that too many hosted zones with the given domain name exist. If you want to create a hosted zone and Amazon Route 53 generates this error, contact Customer Support.</Message></Error></Errors><RequestID>#{Fog::AWS::Mock.request_id}</RequestID></Response>"
102
- raise(Excon::Errors.status_error({:expects => 200}, response))
100
+ raise Fog::DNS::AWS::Error.new("DelegationSetNotAvailable => Amazon Route 53 allows some duplication, but Amazon Route 53 has a maximum threshold of duplicated domains. This error is generated when you reach that threshold. In this case, the error indicates that too many hosted zones with the given domain name exist. If you want to create a hosted zone and Amazon Route 53 generates this error, contact Customer Support.")
103
101
  end
104
102
  end
105
103
  end
@@ -36,14 +36,17 @@ module Fog
36
36
 
37
37
  def delete_hosted_zone(zone_id)
38
38
  response = Excon::Response.new
39
- key = [zone_id, "/hostedzone/#{zone_id}"].find{|k| !self.data[:zones][k].nil?}
40
- if key
39
+ key = [zone_id, "/hostedzone/#{zone_id}"].find { |k| !self.data[:zones][k].nil? } ||
40
+ raise(Fog::DNS::AWS::NotFound.new("NoSuchHostedZone => A hosted zone with the specified hosted zone does not exist."))
41
+
41
42
  change = {
42
43
  :id => Fog::AWS::Mock.change_id,
43
44
  :status => 'INSYNC',
44
45
  :submitted_at => Time.now.utc.iso8601
45
46
  }
47
+
46
48
  self.data[:changes][change[:id]] = change
49
+
47
50
  response.status = 200
48
51
  response.body = {
49
52
  'ChangeInfo' => {
@@ -54,11 +57,6 @@ module Fog
54
57
  }
55
58
  self.data[:zones].delete(key)
56
59
  response
57
- else
58
- response.status = 404
59
- response.body = "<?xml version=\"1.0\"?><ErrorResponse xmlns=\"https://route53.amazonaws.com/doc/2012-02-29/\"><Error><Type>Sender</Type><Code>NoSuchHostedZone</Code><Message>The specified hosted zone does not exist.</Message></Error><RequestId>#{Fog::AWS::Mock.request_id}</RequestId></ErrorResponse>"
60
- raise(Excon::Errors.status_error({:expects => 200}, response))
61
- end
62
60
  end
63
61
  end
64
62
  end
@@ -35,23 +35,18 @@ module Fog
35
35
  response = Excon::Response.new
36
36
  # find the record with matching change_id
37
37
  # records = data[:zones].values.map{|z| z[:records].values.map{|r| r.values}}.flatten
38
- change = self.data[:changes][change_id]
38
+ change = self.data[:changes][change_id] ||
39
+ raise(Fog::DNS::AWS::NotFound.new("NoSuchChange => Could not find resource with ID: #{change_id}"))
39
40
 
40
- if change
41
- response.status = 200
42
- submitted_at = Time.parse(change[:submitted_at])
43
- response.body = {
44
- 'Id' => change[:id],
45
- # set as insync after some time
46
- 'Status' => (submitted_at + Fog::Mock.delay) < Time.now ? 'INSYNC' : change[:status],
47
- 'SubmittedAt' => change[:submitted_at]
48
- }
49
- response
50
- else
51
- response.status = 404
52
- response.body = "<?xml version=\"1.0\"?><ErrorResponse xmlns=\"https://route53.amazonaws.com/doc/2012-02-29/\"><Error><Type>Sender</Type><Code>NoSuchChange</Code><Message>Could not find resource with ID: #{change_id}</Message></Error><RequestId>#{Fog::AWS::Mock.request_id}</RequestId></ErrorResponse>"
53
- raise(Excon::Errors.status_error({:expects => 200}, response))
54
- end
41
+ response.status = 200
42
+ submitted_at = Time.parse(change[:submitted_at])
43
+ response.body = {
44
+ 'Id' => change[:id],
45
+ # set as insync after some time
46
+ 'Status' => (submitted_at + Fog::Mock.delay) < Time.now ? 'INSYNC' : change[:status],
47
+ 'SubmittedAt' => change[:submitted_at]
48
+ }
49
+ response
55
50
  end
56
51
  end
57
52
  end
@@ -51,9 +51,7 @@ module Fog
51
51
  }
52
52
  response
53
53
  else
54
- response.status = 404
55
- response.body = "<?xml version=\"1.0\"?><ErrorResponse xmlns=\"https://route53.amazonaws.com/doc/2012-02-29/\"><Error><Type>Sender</Type><Code>NoSuchHostedZone</Code><Message>The specified hosted zone does not exist.</Message></Error><RequestId>#{Fog::AWS::Mock.request_id}</RequestId></ErrorResponse>"
56
- raise(Excon::Errors.status_error({:expects => 200}, response))
54
+ raise Fog::DNS::AWS::NotFound.new("NoSuchHostedZone => A hosted zone with the specified hosted zone ID does not exist.")
57
55
  end
58
56
  end
59
57
  end
@@ -64,19 +64,15 @@ module Fog
64
64
 
65
65
  response = Excon::Response.new
66
66
 
67
- zone = self.data[:zones][zone_id]
68
- if zone.nil?
69
- response.status = 404
70
- response.body = "<?xml version=\"1.0\"?>\n<ErrorResponse xmlns=\"https://route53.amazonaws.com/doc/2012-02-29/\"><Error><Type>Sender</Type><Code>NoSuchHostedZone</Code><Message>No hosted zone found with ID: #{zone_id}</Message></Error><RequestId>#{Fog::AWS::Mock.request_id}</RequestId></ErrorResponse>"
71
- raise(Excon::Errors.status_error({:expects => 200}, response))
72
- end
67
+ zone = self.data[:zones][zone_id] ||
68
+ raise(Fog::DNS::AWS::NotFound.new("NoSuchHostedZone => A hosted zone with the specified hosted zone ID does not exist."))
73
69
 
74
70
  records = if options[:type]
75
- records_type = zone[:records][options[:type]]
76
- records_type.values if records_type
77
- else
78
- zone[:records].values.map{|r| r.values}.flatten
79
- end
71
+ records_type = zone[:records][options[:type]]
72
+ records_type.values if records_type
73
+ else
74
+ zone[:records].values.map{|r| r.values}.flatten
75
+ end
80
76
 
81
77
  records ||= []
82
78
 
@@ -86,7 +82,6 @@ module Fog
86
82
  if options[:name]
87
83
  name = options[:name].gsub(zone[:name],"")
88
84
  records = records.select{|r| r[:name].gsub(zone[:name],"") >= name }
89
- require 'pp'
90
85
  end
91
86
 
92
87
  next_record = records[maxitems]
@@ -13,7 +13,8 @@ module Fog
13
13
  # * 'Limit'<~Integer> - limit of total items to return
14
14
  # * 'ScanFilter'<~Hash>: value to compare against
15
15
  # * attribute_name<~Hash>:
16
- # * 'AttributeValueList'<~Hash>: one or more values to compare against
16
+ # * 'AttributeValueList'<~Array>: one or more values to compare against
17
+ # * 'AttributeValue'<~Hash> - formated as {type => value}
17
18
  # * 'ComparisonOperator'<~String>: comparison operator to use with attribute value list, in %w{BETWEEN BEGINS_WITH EQ LE LT GE GT}
18
19
  # * 'ScanIndexForward'<~Boolean>: Whether to scan from start or end of index, defaults to start
19
20
  # * 'ExclusiveStartKey'<~Hash>: Key to start listing from, can be taken from LastEvaluatedKey in response
@@ -0,0 +1,32 @@
1
+ module Fog
2
+ module AWS
3
+ class IAM
4
+ class Real
5
+ require 'fog/aws/parsers/iam/basic'
6
+
7
+ # Attaches a managed policy to a group
8
+ #
9
+ # ==== Parameters
10
+ # * group_name<~String>: name of the group
11
+ # * policy_arn<~String>: arn of the managed policy
12
+ #
13
+ # ==== Returns
14
+ # * response<~Excon::Response>:
15
+ # * body<~Hash>:
16
+ # * 'RequestId'<~String> - Id of the request
17
+ #
18
+ # ==== See Also
19
+ # http://docs.aws.amazon.com/IAM/latest/APIReference/API_AttachGroupPolicy.html
20
+ #
21
+ def attach_group_policy(group_name, policy_arn)
22
+ request(
23
+ 'Action' => 'AttachGroupPolicy',
24
+ 'GroupName' => group_name,
25
+ 'PolicyArn' => policy_arn,
26
+ :parser => Fog::Parsers::AWS::IAM::Basic.new
27
+ )
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,32 @@
1
+ module Fog
2
+ module AWS
3
+ class IAM
4
+ class Real
5
+ require 'fog/aws/parsers/iam/basic'
6
+
7
+ # Attaches a managed policy to a role
8
+ #
9
+ # ==== Parameters
10
+ # * role_name<~String>: name of the role
11
+ # * policy_arn<~String>: arn of the managed policy
12
+ #
13
+ # ==== Returns
14
+ # * response<~Excon::Response>:
15
+ # * body<~Hash>:
16
+ # * 'RequestId'<~String> - Id of the request
17
+ #
18
+ # ==== See Also
19
+ # http://docs.aws.amazon.com/IAM/latest/APIReference/API_AttachRolePolicy.html
20
+ #
21
+ def attach_role_policy(role_name, policy_arn)
22
+ request(
23
+ 'Action' => 'AttachRolePolicy',
24
+ 'RoleName' => role_name,
25
+ 'PolicyArn' => policy_arn,
26
+ :parser => Fog::Parsers::AWS::IAM::Basic.new
27
+ )
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,32 @@
1
+ module Fog
2
+ module AWS
3
+ class IAM
4
+ class Real
5
+ require 'fog/aws/parsers/iam/basic'
6
+
7
+ # Attaches a managed policy to a user
8
+ #
9
+ # ==== Parameters
10
+ # * user_name<~String>: name of the user
11
+ # * policy_arn<~String>: arn of the managed policy
12
+ #
13
+ # ==== Returns
14
+ # * response<~Excon::Response>:
15
+ # * body<~Hash>:
16
+ # * 'RequestId'<~String> - Id of the request
17
+ #
18
+ # ==== See Also
19
+ # http://docs.aws.amazon.com/IAM/latest/APIReference/API_AttachUserPolicy.html
20
+ #
21
+ def attach_user_policy(user_name, policy_arn)
22
+ request(
23
+ 'Action' => 'AttachUserPolicy',
24
+ 'UserName' => user_name,
25
+ 'PolicyArn' => policy_arn,
26
+ :parser => Fog::Parsers::AWS::IAM::Basic.new
27
+ )
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,47 @@
1
+ module Fog
2
+ module AWS
3
+ class IAM
4
+ class Real
5
+ require 'fog/aws/parsers/iam/single_policy'
6
+
7
+ # Creates a managed policy
8
+ #
9
+ # ==== Parameters
10
+ # * policy_name<~String>: name of policy document
11
+ # * policy_document<~Hash>: policy document, see: http://docs.amazonwebservices.com/IAM/latest/UserGuide/PoliciesOverview.html
12
+ # * path <~String>: path of the policy
13
+ # * description <~String>: description for the policy
14
+ # ==== Returns
15
+ # * response<~Excon::Response>:
16
+ # * body<~Hash>:
17
+ # * 'RequestId'<~String> - Id of the request
18
+ # * 'Policy'<~Hash>:
19
+ # * Arn
20
+ # * AttachmentCount
21
+ # * CreateDate
22
+ # * DefaultVersionId
23
+ # * Description
24
+ # * IsAttachable
25
+ # * Path
26
+ # * PolicyId
27
+ # * PolicyName
28
+ # * UpdateDate
29
+ # ==== See Also
30
+ # http://docs.aws.amazon.com/IAM/latest/APIReference/API_CreatePolicy.html
31
+ #
32
+ def create_policy(policy_name, policy_document, path=nil, description=nil)
33
+ request({
34
+ 'Action' => 'CreatePolicy',
35
+ 'PolicyName' => policy_name,
36
+ 'PolicyDocument' => Fog::JSON.encode(policy_document),
37
+ 'Path' => path,
38
+ 'Description' => description,
39
+ :parser => Fog::Parsers::AWS::IAM::SinglePolicy.new
40
+ }.reject {|_, value| value.nil?})
41
+ end
42
+ end
43
+
44
+
45
+ end
46
+ end
47
+ end