fog-aws 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +51 -2
  3. data/lib/fog/aws.rb +29 -27
  4. data/lib/fog/aws/elb.rb +0 -1
  5. data/lib/fog/aws/iam.rb +4 -2
  6. data/lib/fog/aws/kms.rb +180 -0
  7. data/lib/fog/aws/mock.rb +13 -1
  8. data/lib/fog/aws/models/compute/flavors.rb +40 -0
  9. data/lib/fog/aws/models/elasticache/cluster.rb +1 -0
  10. data/lib/fog/aws/models/kms/key.rb +34 -0
  11. data/lib/fog/aws/models/kms/keys.rb +29 -0
  12. data/lib/fog/aws/models/rds/server.rb +33 -26
  13. data/lib/fog/aws/parsers/compute/describe_reserved_instances.rb +1 -1
  14. data/lib/fog/aws/parsers/elasticache/cache_cluster_parser.rb +15 -3
  15. data/lib/fog/aws/parsers/kms/describe_key.rb +34 -0
  16. data/lib/fog/aws/parsers/kms/list_keys.rb +38 -0
  17. data/lib/fog/aws/parsers/rds/db_parser.rb +7 -14
  18. data/lib/fog/aws/rds.rb +1 -1
  19. data/lib/fog/aws/requests/compute/describe_spot_price_history.rb +59 -0
  20. data/lib/fog/aws/requests/compute/request_spot_instances.rb +80 -0
  21. data/lib/fog/aws/requests/dns/change_resource_record_sets.rb +36 -5
  22. data/lib/fog/aws/requests/dns/list_resource_record_sets.rb +33 -5
  23. data/lib/fog/aws/requests/elb/create_load_balancer.rb +15 -2
  24. data/lib/fog/aws/requests/iam/create_role.rb +5 -5
  25. data/lib/fog/aws/requests/kms/create_key.rb +62 -0
  26. data/lib/fog/aws/requests/kms/describe_key.rb +27 -0
  27. data/lib/fog/aws/requests/kms/list_keys.rb +82 -0
  28. data/lib/fog/aws/requests/rds/create_db_instance.rb +33 -38
  29. data/lib/fog/aws/requests/rds/create_db_instance_read_replica.rb +7 -2
  30. data/lib/fog/aws/requests/rds/promote_read_replica.rb +7 -6
  31. data/lib/fog/aws/requests/sns/subscribe.rb +1 -1
  32. data/lib/fog/aws/storage.rb +6 -3
  33. data/lib/fog/aws/version.rb +1 -1
  34. data/tests/helper.rb +2 -2
  35. data/tests/models/rds/helper.rb +10 -3
  36. data/tests/models/rds/server_tests.rb +7 -4
  37. data/tests/requests/compute/spot_instance_tests.rb +2 -2
  38. data/tests/requests/compute/spot_price_history_tests.rb +0 -2
  39. data/tests/requests/kms/helper.rb +27 -0
  40. data/tests/requests/kms/key_tests.rb +23 -0
  41. data/tests/requests/rds/helper.rb +52 -46
  42. data/tests/requests/rds/instance_tests.rb +16 -12
  43. metadata +12 -2
@@ -151,6 +151,19 @@ module Fog
151
151
  end
152
152
 
153
153
  class Mock
154
+ SET_PREFIX = 'SET_'
155
+ def record_exist?(zone,change,change_name)
156
+ return false if zone[:records][change[:type]].nil?
157
+ current_records = zone[:records][change[:type]][change_name]
158
+ return false if current_records.nil?
159
+
160
+ if !change[:set_identifier].empty?
161
+ !current_records[change[:SetIdentifier]].nil?
162
+ else
163
+ !current_records.empty?
164
+ end
165
+ end
166
+
154
167
  def change_resource_record_sets(zone_id, change_batch, options = {})
155
168
  response = Excon::Response.new
156
169
  errors = []
@@ -171,9 +184,9 @@ module Fog
171
184
  zone[:records][change[:type]] = {}
172
185
  end
173
186
 
174
- if zone[:records][change[:type]][change_name].nil?
187
+ if !record_exist?(zone, change, change_name)
175
188
  # raise change.to_s if change[:resource_records].nil?
176
- zone[:records][change[:type]][change_name] =
189
+ new_record =
177
190
  if change[:alias_target]
178
191
  record = {
179
192
  :alias_target => change[:alias_target]
@@ -183,17 +196,35 @@ module Fog
183
196
  :ttl => change[:ttl].to_s,
184
197
  }
185
198
  end
186
- zone[:records][change[:type]][change_name] = {
199
+
200
+ new_record = {
187
201
  :change_id => change_id,
188
202
  :resource_records => change[:resource_records] || [],
189
203
  :name => change_name,
190
- :type => change[:type]
204
+ :type => change[:type],
205
+ :set_identifier => change[:set_identifier],
206
+ :weight => change[:weight]
191
207
  }.merge(record)
208
+
209
+ if change[:set_identifier].nil?
210
+ zone[:records][change[:type]][change_name] = new_record
211
+ else
212
+ zone[:records][change[:type]][change_name] = {} if zone[:records][change[:type]][change_name].nil?
213
+ zone[:records][change[:type]][change_name][SET_PREFIX + change[:set_identifier]] = new_record
214
+ end
192
215
  else
193
216
  errors << "Tried to create resource record set #{change[:name]}. type #{change[:type]}, but it already exists"
194
217
  end
195
218
  when "DELETE"
196
- if zone[:records][change[:type]].nil? || zone[:records][change[:type]].delete(change_name).nil?
219
+ action_performed = false
220
+ if !zone[:records][change[:type]].nil? && !zone[:records][change[:type]][change_name].nil? && !change[:set_identifier].nil?
221
+ action_performed = true unless zone[:records][change[:type]][change_name].delete(SET_PREFIX + change[:set_identifier]).nil?
222
+ zone[:records][change[:type]].delete(change_name) if zone[:records][change[:type]][change_name].empty?
223
+ elsif !zone[:records][change[:type]].nil?
224
+ action_performed = true unless zone[:records][change[:type]].delete(change_name).nil?
225
+ end
226
+
227
+ if !action_performed
197
228
  errors << "Tried to delete resource record set #{change[:name]}. type #{change[:type]}, but it was not found"
198
229
  end
199
230
  end
@@ -59,6 +59,22 @@ module Fog
59
59
  end
60
60
 
61
61
  class Mock
62
+ def list_all_records(record, zone, name)
63
+ [].tap do |tmp_records|
64
+ tmp_records.push(record) if !record[:name].nil? && ( name.nil? || record[:name].gsub(zone[:name],"") >= name)
65
+ record.each do |key,subr|
66
+ if subr.is_a?(Hash) && key.is_a?(String) &&
67
+ key.start_with?(Fog::DNS::AWS::Mock::SET_PREFIX)
68
+ if name.nil?
69
+ tmp_records.append(subr)
70
+ else
71
+ tmp_records.append(subr) if !subr[:name].nil? && subr[:name].gsub(zone[:name],"") >= name
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+
62
78
  def list_resource_record_sets(zone_id, options = {})
63
79
  maxitems = [options[:max_items]||100,100].min
64
80
 
@@ -76,13 +92,23 @@ module Fog
76
92
 
77
93
  records ||= []
78
94
 
79
- # sort for pagination
80
- records.sort! { |a,b| a[:name].gsub(zone[:name],"") <=> b[:name].gsub(zone[:name],"") }
81
-
95
+ tmp_records = []
82
96
  if options[:name]
83
97
  name = options[:name].gsub(zone[:name],"")
84
- records = records.select{|r| r[:name].gsub(zone[:name],"") >= name }
98
+
99
+ records.each do |r|
100
+ tmp_records += list_all_records(r, zone, name)
101
+ end
102
+ else
103
+ records.each do |r|
104
+ tmp_records += list_all_records(r, zone, nil)
105
+ end
85
106
  end
107
+ records = tmp_records
108
+
109
+ # sort for pagination
110
+ records.sort! { |a,b| a[:name].gsub(zone[:name],"") <=> b[:name].gsub(zone[:name],"") }
111
+
86
112
 
87
113
  next_record = records[maxitems]
88
114
  records = records[0, maxitems]
@@ -106,7 +132,9 @@ module Fog
106
132
  {
107
133
  'ResourceRecords' => r[:resource_records],
108
134
  'Name' => r[:name],
109
- 'Type' => r[:type]
135
+ 'Type' => r[:type],
136
+ 'SetIdentifier' => r[:set_identifier],
137
+ 'Weight' => r[:weight]
110
138
  }.merge(record)
111
139
  end,
112
140
  'MaxItems' => maxitems,
@@ -74,9 +74,22 @@ module Fog
74
74
  dns_name = Fog::AWS::ELB::Mock.dns_name(lb_name, @region)
75
75
 
76
76
  availability_zones = [*availability_zones].compact
77
- region = availability_zones.empty? ? "us-east-1" : availability_zones.first.gsub(/[a-z]$/, '')
78
- supported_platforms = Fog::Compute::AWS::Mock.data[region][@aws_access_key_id][:account_attributes].find { |h| h["attributeName"] == "supported-platforms" }["values"]
79
77
  subnet_ids = options[:subnet_ids] || []
78
+ region = if availability_zones.any?
79
+ availability_zones.first.gsub(/[a-z]$/, '')
80
+ elsif subnet_ids.any?
81
+ # using Hash here for Rubt 1.8.7 support.
82
+ Hash[
83
+ Fog::Compute::AWS::Mock.data.select do |_, region_data|
84
+ region_data[@aws_access_key_id][:subnets].any? do |region_subnets|
85
+ subnet_ids.include? region_subnets['subnetId']
86
+ end
87
+ end
88
+ ].keys[0]
89
+ else
90
+ 'us-east-1'
91
+ end
92
+ supported_platforms = Fog::Compute::AWS::Mock.data[region][@aws_access_key_id][:account_attributes].find { |h| h["attributeName"] == "supported-platforms" }["values"]
80
93
  subnets = Fog::Compute::AWS::Mock.data[region][@aws_access_key_id][:subnets].select {|e| subnet_ids.include?(e["subnetId"]) }
81
94
 
82
95
  # http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/default-vpc.html
@@ -42,11 +42,11 @@ module Fog
42
42
  #
43
43
  def create_role(role_name, assume_role_policy_document, path = '/')
44
44
  request(
45
- 'Action' => 'CreateRole',
46
- 'RoleName' => role_name,
47
- 'AssumeRolePolicyDocument' => assume_role_policy_document,
48
- 'Path' => path,
49
- :parser => Fog::Parsers::AWS::IAM::SingleRole.new
45
+ 'Action' => 'CreateRole',
46
+ 'RoleName' => role_name,
47
+ 'AssumeRolePolicyDocument' => assume_role_policy_document,
48
+ 'Path' => path,
49
+ :parser => Fog::Parsers::AWS::IAM::SingleRole.new
50
50
  )
51
51
  end
52
52
  end
@@ -0,0 +1,62 @@
1
+ module Fog
2
+ module AWS
3
+ class KMS
4
+ class Real
5
+ DEFAULT_KEY_POLICY = <<-JSON
6
+ {
7
+ "Version": "2012-10-17",
8
+ "Id": "key-default-1",
9
+ "Statement": [
10
+ {
11
+ "Sid": "Enable IAM User Permissions",
12
+ "Effect": "Allow",
13
+ "Principal": {
14
+ "AWS": "arn:aws:iam::915445820265:root"
15
+ },
16
+ "Action": "kms:*",
17
+ "Resource": "*"
18
+ }
19
+ ]
20
+ }
21
+ JSON
22
+
23
+ require 'fog/aws/parsers/kms/describe_key'
24
+
25
+ def create_key(policy = nil, description = nil, usage = "ENCRYPT_DECRYPT")
26
+ request(
27
+ 'Action' => 'CreateKey',
28
+ 'Description' => description,
29
+ 'KeyUsage' => usage,
30
+ 'Policy' => policy,
31
+ :parser => Fog::Parsers::AWS::KMS::DescribeKey.new
32
+ )
33
+ end
34
+ end
35
+
36
+ class Mock
37
+ def create_key(policy = nil, description = nil, usage = "ENCRYPT_DECRYPT")
38
+ response = Excon::Response.new
39
+ key_id = UUID.uuid
40
+ key_arn = Fog::AWS::Mock.arn("kms", self.account_id, "key/#{key_id}", @region)
41
+
42
+ key = {
43
+ "KeyUsage" => usage,
44
+ "AWSAccountId" => self.account_id,
45
+ "KeyId" => key_id,
46
+ "Description" => description,
47
+ "CreationDate" => Time.now,
48
+ "Arn" => key_arn,
49
+ "Enabled" => true,
50
+ }
51
+
52
+ # @todo use default policy
53
+
54
+ self.data[:keys][key_id] = key
55
+
56
+ response.body = { "KeyMetadata" => key }
57
+ response
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,27 @@
1
+ module Fog
2
+ module AWS
3
+ class KMS
4
+ class Real
5
+ require 'fog/aws/parsers/kms/describe_key'
6
+
7
+ def describe_key(identifier)
8
+ request(
9
+ 'Action' => 'DescribeKey',
10
+ 'KeyId' => identifier,
11
+ :parser => Fog::Parsers::AWS::KMS::DescribeKey.new
12
+ )
13
+ end
14
+ end
15
+
16
+ class Mock
17
+ def describe_key(identifier)
18
+ response = Excon::Response.new
19
+ key = self.data[:keys][identifier]
20
+
21
+ response.body = { "KeyMetadata" => key }
22
+ response
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,82 @@
1
+ module Fog
2
+ module AWS
3
+ class KMS
4
+ class Real
5
+
6
+ require 'fog/aws/parsers/kms/list_keys'
7
+
8
+ def list_keys(options={})
9
+ params = {}
10
+
11
+ if options[:marker]
12
+ params['Marker'] = options[:marker]
13
+ end
14
+
15
+ if options[:limit]
16
+ params['Limit'] = options[:limit]
17
+ end
18
+
19
+ request({
20
+ 'Action' => 'ListKeys',
21
+ :parser => Fog::Parsers::AWS::KMS::ListKeys.new
22
+ }.merge(params))
23
+ end
24
+ end
25
+
26
+ class Mock
27
+ def list_keys(options={})
28
+ limit = options[:limit]
29
+ marker = options[:marker]
30
+
31
+ if limit
32
+ if limit > 1_000
33
+ raise Fog::AWS::KMS::Error.new(
34
+ "ValidationError => 1 validation error detected: Value '#{limit}' at 'limit' failed to satisfy constraint: Member must have value less than or equal to 1000"
35
+ )
36
+ elsif limit < 1
37
+ raise Fog::AWS::KMS::Error.new(
38
+ "ValidationError => 1 validation error detected: Value '#{limit}' at 'limit' failed to satisfy constraint: Member must have value greater than or equal to 1"
39
+ )
40
+ end
41
+ end
42
+
43
+ key_set = if marker
44
+ self.data[:markers][marker] || []
45
+ else
46
+ self.data[:keys].inject([]) { |r,(k,v)|
47
+ r << { "KeyId" => k, "KeyArn" => v["Arn"] }
48
+ }
49
+ end
50
+
51
+ keys = if limit
52
+ key_set.slice!(0, limit)
53
+ else
54
+ key_set
55
+ end
56
+
57
+ truncated = keys.size < key_set.size
58
+
59
+ marker = truncated && "metadata/l/#{account_id}/#{UUID.uuid}"
60
+
61
+ response = Excon::Response.new
62
+
63
+ body = {
64
+ 'Keys' => keys,
65
+ 'Truncated' => truncated,
66
+ 'RequestId' => Fog::AWS::Mock.request_id
67
+ }
68
+
69
+ if marker
70
+ self.data[:markers][marker] = key_set
71
+ body.merge!('Marker' => marker)
72
+ end
73
+
74
+ response.body = body
75
+ response.status = 200
76
+
77
+ response
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -25,7 +25,7 @@ module Fog
25
25
  # @param PreferredBackupWindow [String] The daily time range during which automated backups are created if automated backups are enabled
26
26
  # @param PreferredMaintenanceWindow [String] The weekly time range (in UTC) during which system maintenance can occur, which may result in an outage
27
27
  # @param DBSubnetGroupName [String] The name, if any, of the VPC subnet for this RDS instance
28
- # @param PubliclyAcccesible [Boolean] Whether an RDS instance inside of the VPC subnet should have a public-facing endpoint
28
+ # @param PubliclyAccessible [Boolean] Whether an RDS instance inside of the VPC subnet should have a public-facing endpoint
29
29
  # @param VpcSecurityGroups [Array] A list of VPC Security Groups to authorize on this DB instance
30
30
  # @param StorageType [string] Specifies storage type to be associated with the DB Instance. Valid values: standard | gp2 | io1
31
31
  #
@@ -43,9 +43,9 @@ module Fog
43
43
  end
44
44
 
45
45
  request({
46
- 'Action' => 'CreateDBInstance',
46
+ 'Action' => 'CreateDBInstance',
47
47
  'DBInstanceIdentifier' => db_name,
48
- :parser => Fog::Parsers::AWS::RDS::CreateDBInstance.new,
48
+ :parser => Fog::Parsers::AWS::RDS::CreateDBInstance.new,
49
49
  }.merge(options))
50
50
  end
51
51
  end
@@ -78,41 +78,36 @@ module Fog
78
78
  end
79
79
  end
80
80
 
81
- data =
82
- {
83
- "DBInstanceIdentifier"=> db_name,
84
- "DBName" => options["DBName"],
85
- "InstanceCreateTime" => nil,
86
- "AutoMinorVersionUpgrade"=>true,
87
- "Endpoint"=>{},
88
- "ReadReplicaDBInstanceIdentifiers"=>[],
89
- "PreferredMaintenanceWindow"=>"mon:04:30-mon:05:00",
90
- "Engine"=> options["Engine"],
91
- "EngineVersion"=> options["EngineVersion"] || "5.5.12",
92
- "PendingModifiedValues"=>{"MasterUserPassword"=>"****"}, # This clears when is available
93
- "MultiAZ"=> !!options['MultiAZ'],
94
- "MasterUsername"=> options["MasterUsername"],
95
- "DBInstanceClass"=> options["DBInstanceClass"],
96
- "DBInstanceStatus"=>"creating",
97
- "BackupRetentionPeriod"=> options["BackupRetentionPeriod"] || 1,
98
- "AllocatedStorage"=> options["AllocatedStorage"],
99
- "Iops" => options["Iops"],
100
- "DBParameterGroups"=> # I think groups should be in the self.data method
101
- [{"DBParameterGroupName"=>"default.mysql5.5",
102
- "ParameterApplyStatus"=>"in-sync"}],
103
- "DBSecurityGroups"=>
104
- [{"Status"=>"active",
105
- "DBSecurityGroupName"=>"default"}],
106
- "LicenseModel"=>"general-public-license",
107
- "PreferredBackupWindow"=>"08:00-08:30",
108
- # "ReadReplicaSourceDBInstanceIdentifier" => nil,
109
- # "LatestRestorableTime" => nil,
110
- "AvailabilityZone" => options["AvailabilityZone"],
111
- "DBSubnetGroupName" => options["DBSubnetGroupName"],
112
- "PubliclyAccessible" => options["PubliclyAccessible"],
113
- "VpcSecurityGroups" => options["VpcSecurityGroups"],
114
- "StorageType" => options["StorageType"],
115
- }
81
+ data = {
82
+ "AllocatedStorage" => options["AllocatedStorage"],
83
+ "AutoMinorVersionUpgrade" => options["AutoMinorVersionUpgrade"].nil? ? true : options["AutoMinorVersionUpgrade"],
84
+ "AvailabilityZone" => options["AvailabilityZone"],
85
+ "BackupRetentionPeriod" => options["BackupRetentionPeriod"] || 1,
86
+ "CACertificateIdentifier" => "rds-ca-2015",
87
+ "DBInstanceClass" => options["DBInstanceClass"],
88
+ "DBInstanceIdentifier" => db_name,
89
+ "DBInstanceStatus" =>"creating",
90
+ "DBName" => options["DBName"],
91
+ "DBParameterGroups" => [{ "DBParameterGroupName" => "default.mysql5.5", "ParameterApplyStatus" => "in-sync" }],
92
+ "DBSecurityGroups" => [{ "Status" => "active", "DBSecurityGroupName" => "default" }],
93
+ "DBSubnetGroupName" => options["DBSubnetGroupName"],
94
+ "Endpoint" =>{},
95
+ "Engine" => options["Engine"],
96
+ "EngineVersion" => options["EngineVersion"] || "5.5.12",
97
+ "InstanceCreateTime" => nil,
98
+ "Iops" => options["Iops"],
99
+ "LicenseModel" => "general-public-license",
100
+ "MasterUsername" => options["MasterUsername"],
101
+ "MultiAZ" => !!options['MultiAZ'],
102
+ "PendingModifiedValues" => { "MasterUserPassword" => "****" }, # This clears when is available
103
+ "PreferredBackupWindow" => options["PreferredBackupWindow"] || "08:00-08:30",
104
+ "PreferredMaintenanceWindow" => options["PreferredMaintenanceWindow"] || "mon:04:30-mon:05:00",
105
+ "PubliclyAccessible" => !!options["PubliclyAccessible"],
106
+ "ReadReplicaDBInstanceIdentifiers" => [],
107
+ "StorageEncrypted" => false,
108
+ "StorageType" => options["StorageType"] || "standard",
109
+ "VpcSecurityGroups" => options["VpcSecurityGroups"],
110
+ }
116
111
 
117
112
  self.data[:servers][db_name] = data
118
113
  response.body = {
@@ -34,8 +34,10 @@ module Fog
34
34
  source = self.data[:servers][source_identifier]
35
35
  data = {
36
36
  'AllocatedStorage' => source['AllocatedStorage'],
37
- 'AutoMinorVersionUpgrade' => options.key?('AutoMinorVersionUpgrade') ? options['AutoMinorVersionUpgrade'] : true,
37
+ 'AutoMinorVersionUpgrade' => options.key?('AutoMinorVersionUpgrade') ? options['AutoMinorVersionUpgrade'] : source['AutoMinorVersionUpgrade'],
38
38
  'AvailabilityZone' => options['AvailabilityZone'],
39
+ 'BackupRetentionPeriod' => options['BackupRetentionPeriod'] || 0,
40
+ 'CACertificateIdentifier' => "rds-ca-2015",
39
41
  'DBInstanceClass' => options['DBInstanceClass'] || 'db.m1.small',
40
42
  'DBInstanceIdentifier' => instance_identifier,
41
43
  'DBInstanceStatus' => 'creating',
@@ -54,8 +56,11 @@ module Fog
54
56
  'PendingModifiedValues' => {},
55
57
  'PreferredBackupWindow' => '08:00-08:30',
56
58
  'PreferredMaintenanceWindow' => "mon:04:30-mon:05:00",
59
+ 'PubliclyAccessible' => !!options["PubliclyAccessible"],
57
60
  'ReadReplicaDBInstanceIdentifiers' => [],
58
- 'ReadReplicaSourceDBInstanceIdentifier' => source_identifier
61
+ 'ReadReplicaSourceDBInstanceIdentifier' => source_identifier,
62
+ 'StorageType' => options['StorageType'] || 'standard',
63
+ 'StorageEncrypted' => false,
59
64
  }
60
65
  self.data[:servers][instance_identifier] = data
61
66
  self.data[:servers][source_identifier]['ReadReplicaDBInstanceIdentifiers'] << instance_identifier