diff --git a/lib/fog/aws.rb b/lib/fog/aws.rb index 3e0903c0f..95f641263 100644 --- a/lib/fog/aws.rb +++ b/lib/fog/aws.rb @@ -223,6 +223,10 @@ module Fog def self.volume_id "vol-#{Fog::Mock.random_hex(8)}" end + + def self.rds_address(db_name,region) + "#{db_name}.#{Fog::Mock.random_letters(rand(12) + 4)}.#{region}.rds.amazonaws.com" + end end end end diff --git a/lib/fog/aws/rds.rb b/lib/fog/aws/rds.rb index a4fe2af0d..88e9a973b 100644 --- a/lib/fog/aws/rds.rb +++ b/lib/fog/aws/rds.rb @@ -57,9 +57,42 @@ module Fog class Mock - def initialize(options={}) - Fog::Mock.not_implemented + def self.data + @data ||= Hash.new do |hash, region| + owner_id = Fog::AWS::Mock.owner_id + hash[region] = Hash.new do |region_hash, key| + region_hash[key] = { + :servers => {} + } + end + end end + + def self.reset + @data = nil + end + + def initialize(options={}) + + @aws_access_key_id = options[:aws_access_key_id] + + @region = options[:region] || 'us-east-1' + + unless ['ap-northeast-1', 'ap-southeast-1', 'eu-west-1', 'us-east-1', 'us-west-1', 'us-west-2'].include?(@region) + raise ArgumentError, "Unknown region: #{@region.inspect}" + end + + end + + def data + self.class.data[@region][@aws_access_key_id] + end + + def reset_data + self.class.data[@region].delete(@aws_access_key_id) + end + + end diff --git a/lib/fog/aws/requests/rds/create_db_instance.rb b/lib/fog/aws/requests/rds/create_db_instance.rb index 9332f30f0..8879e2ec4 100644 --- a/lib/fog/aws/requests/rds/create_db_instance.rb +++ b/lib/fog/aws/requests/rds/create_db_instance.rb @@ -47,7 +47,70 @@ module Fog class Mock def create_db_instance(db_name, options={}) - Fog::Mock.not_implemented + response = Excon::Response.new + if self.data[:servers] and self.data[:servers][db_name] + # I don't know how to raise an exception that contains the excon data + #response.status = 400 + #response.body = { + # 'Code' => 'DBInstanceAlreadyExists', + # 'Message' => "DB Instance already exists" + #} + #return response + raise Fog::AWS::RDS::IdentifierTaken.new("DBInstanceAlreadyExists #{response.body.to_s}") + end + + # These are the required parameters according to the API + required_params = %w{AllocatedStorage DBInstanceClass Engine MasterUserPassword MasterUsername } + required_params.each do |key| + unless options.has_key?(key) and options[key] and !options[key].to_s.empty? + #response.status = 400 + #response.body = { + # 'Code' => 'MissingParameter', + # 'Message' => "The request must contain the parameter #{key}" + #} + #return response + raise Fog::AWS::RDS::NotFound.new("The request must contain the parameter #{key}") + end + end + + data = + { + "DBInstanceIdentifier"=> db_name, + "DBName" => options["DBName"], + "created_at" => nil, + "AutoMinorVersionUpgrade"=>true, + "Endpoint"=>{}, + "ReadReplicaDBInstanceIdentifiers"=>[], + "PreferredMaintenanceWindow"=>"mon:04:30-mon:05:00", + "Engine"=> options["Engine"], + "EngineVersion"=> options["EngineVersion"] || "5.1.57", + "PendingModifiedValues"=>{"MasterUserPassword"=>"****"}, # This clears when is available + "MultiAZ"=>false, + "MasterUsername"=> options["MasterUsername"], + "DBInstanceClass"=> options["DBInstanceClass"], + "DBInstanceStatus"=>"creating", + "BackupRetentionPeriod"=> options["BackupRetentionPeriod"] || 1, + "AllocatedStorage"=> options["AllocatedStorage"], + "DBParameterGroups"=> # I think groups shoul be in the self.data method + [{"DBParameterGroupName"=>"default.mysql5.1", + "ParameterApplyStatus"=>"in-sync"}], + "DBSecurityGroups"=> + [{"Status"=>"active", + "DBSecurityGroupName"=>"default"}], + "LicenseModel"=>"general-public-license", + "PreferredBackupWindow"=>"08:00-08:30" + } + + + self.data[:servers][db_name] = data + response.body = { + "ResponseMetadata"=>{ "RequestId"=> Fog::AWS::Mock.request_id }, + "CreateDBInstanceResult"=> {"DBInstance"=> data} + } + response.status = 200 + # This values aren't showed at creating time but at available time + self.data[:servers][db_name]["created_at"] = Time.now + response end end diff --git a/lib/fog/aws/requests/rds/delete_db_instance.rb b/lib/fog/aws/requests/rds/delete_db_instance.rb index 0c5979b21..170181f72 100644 --- a/lib/fog/aws/requests/rds/delete_db_instance.rb +++ b/lib/fog/aws/requests/rds/delete_db_instance.rb @@ -15,7 +15,7 @@ module Fog # ==== Returns # * response<~Excon::Response>: # * body<~Hash>: - def delete_db_instance(identifier, snapshot_identifier, skip_snapshot = false) + def delete_db_instance(identifier, snapshot_identifier, skip_snapshot = false) params = {} params['FinalDBSnapshotIdentifier'] = snapshot_identifier if snapshot_identifier request({ @@ -30,8 +30,24 @@ module Fog class Mock - def delete_db_snapshot(identifier, snapshot_identifier, skip_snapshot = false) - Fog::Mock.not_implemented + def delete_db_instance(identifier, snapshot_identifier, skip_snapshot = false) + response = Excon::Response.new + + unless skip_snapshot + # I don't know how to mock snapshot_identifier + Fog::Logger.warning("snapshot_identifier is not mocked [light_black](#{caller.first})[/]") + end + + if server_set = self.data[:servers].delete(identifier) + response.status = 200 + response.body = { + "ResponseMetadata"=>{ "RequestId"=> Fog::AWS::Mock.request_id }, + "DeleteDBInstanceResult" => { "DBInstance" => server_set } + } + response + else + raise Fog::AWS::RDS::NotFound.new("DBInstance #{identifier} not found") + end end end diff --git a/lib/fog/aws/requests/rds/describe_db_instances.rb b/lib/fog/aws/requests/rds/describe_db_instances.rb index ea7bd34a1..7e1f0a63b 100644 --- a/lib/fog/aws/requests/rds/describe_db_instances.rb +++ b/lib/fog/aws/requests/rds/describe_db_instances.rb @@ -33,8 +33,46 @@ module Fog class Mock def describe_db_instances(identifier=nil, opts={}) - Fog::Mock.not_implemented + response = Excon::Response.new + server_set = [] + if identifier + if server = self.data[:servers][identifier] + server_set << server + else + raise Fog::AWS::RDS::NotFound.new("DBInstance #{identifier} not found") + end + end + server_set = self.data[:servers].values + + server_set.each do |server| + case server["DBInstanceStatus"] + when "creating" + if Time.now - server['created_at'] >= Fog::Mock.delay * 2 + region = "us-east-1" + server["DBInstanceStatus"] = "available" + server["availability_zone"] = region + 'a' + server["Endpoint"] = {"Port"=>3306, + "Address"=> Fog::AWS::Mock.rds_address(server["DBInstanceIdentifier"],region) } + server["PendingModifiedValues"] = {} + end + when "rebooting" + # it applies pending modified values + if server["PendingModifiedValues"] + server.merge!(server["PendingModifiedValues"]) + server["PendingModifiedValues"] = {} + server["DBInstanceStatus"] = 'available' + end + end + end + + response.status = 200 + response.body = { + "ResponseMetadata"=>{ "RequestId"=> Fog::AWS::Mock.request_id }, + "DescribeDBInstancesResult" => { "DBInstances" => server_set } + } + response end + end end diff --git a/lib/fog/aws/requests/rds/describe_db_reserved_instances.rb b/lib/fog/aws/requests/rds/describe_db_reserved_instances.rb index cafbb502e..ab089110e 100644 --- a/lib/fog/aws/requests/rds/describe_db_reserved_instances.rb +++ b/lib/fog/aws/requests/rds/describe_db_reserved_instances.rb @@ -32,7 +32,7 @@ module Fog class Mock - def describe_db_instances(identifier=nil, opts={}) + def describe_db_reserved_instances(identifier=nil, opts={}) Fog::Mock.not_implemented end diff --git a/lib/fog/aws/requests/rds/modify_db_instance.rb b/lib/fog/aws/requests/rds/modify_db_instance.rb index c6e51282e..abfe64467 100644 --- a/lib/fog/aws/requests/rds/modify_db_instance.rb +++ b/lib/fog/aws/requests/rds/modify_db_instance.rb @@ -45,7 +45,30 @@ module Fog class Mock def modify_db_instance(db_name, apply_immediately, options={}) - Fog::Mock.not_implemented + response = Excon::Response.new + if server = self.data[:servers][db_name] + if server["DBInstanceStatus"] != "available" + raise Fog::AWS::RDS::NotFound.new("DBInstance #{db_name} not available for modification") + else + # TODO verify the params options + # if apply_immediately is false, all the options go to pending_modified_values and then apply and clear after either + # a reboot or the maintainance window + if apply_immediately + modified_server = server.merge(options) + else + modified_server = server["PendingModifiedValues"].merge!(options) # it appends + end + response.status = 200 + response.body = { + "ResponseMetadata"=>{ "RequestId"=> Fog::AWS::Mock.request_id }, + "ModifyDBInstanceResult" => { "DBInstance" => modified_server } + } + response + + end + else + raise Fog::AWS::RDS::NotFound.new("DBInstance #{db_name} not found") + end end end diff --git a/lib/fog/aws/requests/rds/reboot_db_instance.rb b/lib/fog/aws/requests/rds/reboot_db_instance.rb index 7d54b70a8..ef04120bd 100644 --- a/lib/fog/aws/requests/rds/reboot_db_instance.rb +++ b/lib/fog/aws/requests/rds/reboot_db_instance.rb @@ -25,7 +25,23 @@ module Fog class Mock def reboot_db_instance(instance_identifier) - Fog::Mock.not_implemented + response = Excon::Response.new + if server = self.data[:servers][instance_identifier] + if server["DBInstanceStatus"] != "available" + raise Fog::AWS::RDS::NotFound.new("DBInstance #{db_name} not available for rebooting") + else + server["DBInstanceStatus"] = 'rebooting' + response.status = 200 + response.body = { + "ResponseMetadata"=>{ "RequestId"=> Fog::AWS::Mock.request_id }, + "RebootDBInstanceResult" => { "DBInstance" => server } + } + response + + end + else + raise Fog::AWS::RDS::NotFound.new("DBInstance #{db_name} not found") + end end end