1
0
Fork 0
mirror of https://github.com/fog/fog.git synced 2022-11-09 13:51:43 -05:00

Merge pull request #764 from ktheory/improve_rds_mocks

[aws|rds] Add mock support for DB snapshots
This commit is contained in:
Wesley Beary 2012-02-27 07:08:37 -08:00
commit 7306dfe159
16 changed files with 149 additions and 77 deletions

View file

@ -65,7 +65,8 @@ module Fog
hash[region] = Hash.new do |region_hash, key|
region_hash[key] = {
:servers => {},
:security_groups => {}
:security_groups => {},
:snapshots => {}
}
end
end

View file

@ -9,15 +9,15 @@ module Fog
# http://docs.amazonwebservices.com/AmazonRDS/latest/APIReference/API_CreateDBInstance.html
# ==== Parameters
# * DBInstanceIdentifier <~String> - name of the db instance to modify
#
#
# * AllocatedStorage <~Integer> Storage space, in GB
# * AutoMinorVersionUpgrade <~Boolean> Indicates that minor version upgrades will be applied automatically to the DB Instance during the maintenance window
# * AutoMinorVersionUpgrade <~Boolean> Indicates that minor version upgrades will be applied automatically to the DB Instance during the maintenance window
# * AvailabilityZone <~String> The availability zone to create the instance in
# * BackupRetentionPeriod <~Integer> 0-8 The number of days to retain automated backups.
# * DBInstanceClass <~String> The new compute and memory capacity of the DB Instance
# * DBName <~String> The name of the database to create when the DB Instance is created
# * DBParameterGroupName <~String> The name of the DB Parameter Group to apply to this DB Instance
# * DBSecurityGroups <~Array> A list of DB Security Groups to authorize on this DB Instance
# * DBParameterGroupName <~String> The name of the DB Parameter Group to apply to this DB Instance
# * DBSecurityGroups <~Array> A list of DB Security Groups to authorize on this DB Instance
# * Engine <~String> The name of the database engine to be used for this instance.
# * EngineVersion <~String> The version number of the database engine to use.
# * MasterUsername <~String> The db master user
@ -30,11 +30,11 @@ module Fog
# * response<~Excon::Response>:
# * body<~Hash>:
def create_db_instance(db_name, options={})
if security_groups = options.delete('DBSecurityGroups')
options.merge!(Fog::AWS.indexed_param('DBSecurityGroups.member.%d', [*security_groups]))
end
request({
'Action' => 'CreateDBInstance',
'DBInstanceIdentifier' => db_name,
@ -58,7 +58,7 @@ module Fog
#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|
@ -72,7 +72,7 @@ module Fog
raise Fog::AWS::RDS::NotFound.new("The request must contain the parameter #{key}")
end
end
data =
{
"DBInstanceIdentifier"=> db_name,
@ -103,8 +103,8 @@ module Fog
# "LatestRestorableTime" => nil,
"AvailabilityZone" => options["AvailabilityZone"]
}
self.data[:servers][db_name] = data
response.body = {
"ResponseMetadata"=>{ "RequestId"=> Fog::AWS::Mock.request_id },

View file

@ -27,9 +27,45 @@ module Fog
class Mock
def create_db_snapshot(identifier, name)
Fog::Mock.not_implemented
end
response = Excon::Response.new
if data[:snapshots][name]
raise Fog::AWS::RDS::IndentifierTaken.new
end
server_data = data[:servers][identifier]
unless server_data
raise Fog::AWS::RDS::NotFound.new("DBInstance #{identifier} not found")
end
# TODO: raise an error if the server isn't in 'available' state
snapshot_data = {
'Status' => 'creating',
#'SnapshotType' => 'manual', # In a newer RDS version
'DBInstanceIdentifier' => identifier,
'DBSnapshotIdentifier' => name,
'InstanceCreateTime' => Time.now
}
# Copy attributes from server
%w(Engine EngineVersion AvailabilityZone AllocatedStorage MasterUsername InstanceCreateTime).each do |key|
snapshot_data[key] = server_data[key]
end
snapshot_data['Port'] = server_data['Endpoint']['Port']
self.data[:snapshots][name] = snapshot_data
# TODO: put the server in 'modifying' state
response.body = {
"ResponseMetadata"=>{ "RequestId"=> Fog::AWS::Mock.request_id },
"CreateDBSnapshotResult"=> {"DBSnapshot"=> snapshot_data.dup}
}
response.status = 200
# SnapshotCreateTime is not part of the response.
self.data[:snapshots][name]['SnapshotCreateTime'] = Time.now
response
end
end
end
end

View file

@ -34,8 +34,7 @@ module Fog
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})[/]")
create_db_snapshot(identifier, snapshot_identifier)
end
if server_set = self.data[:servers].delete(identifier)

View file

@ -12,11 +12,11 @@ module Fog
# ==== Returns
# * response<~Excon::Response>:
# * body<~Hash>:
def delete_db_snapshot(group_name)
def delete_db_snapshot(name)
request({
'Action' => 'DeleteDBSnapshot',
'DBSnapshotIdentifier' => group_name,
'DBSnapshotIdentifier' => name,
:parser => Fog::Parsers::AWS::RDS::DeleteDBSnapshot.new
})
@ -26,8 +26,19 @@ module Fog
class Mock
def delete_db_snapshot(group_name)
Fog::Mock.not_implemented
def delete_db_snapshot(name)
# TODO: raise error if snapshot isn't 'available'
response = Excon::Response.new
snapshot_data = self.data[:snapshots].delete(name)
raise Fog::AWS::RDS::NotFound.new("DBSnapshtoNotFound => #{name} not found") unless snapshot_data
response.status = 200
response.body = {
"ResponseMetadata"=> { "RequestId"=> Fog::AWS::Mock.request_id },
"DeleteDBSnapshotResult"=> {"DBSnapshot"=> snapshot_data}
}
response
end
end

View file

@ -21,7 +21,7 @@ module Fog
if opts[:max_records]
params['MaxRecords'] = opts[:max_records]
end
request({
'Action' => 'DescribeDBInstances',
:parser => Fog::Parsers::AWS::RDS::DescribeDBInstances.new
@ -35,7 +35,7 @@ module Fog
def describe_db_instances(identifier=nil, opts={})
response = Excon::Response.new
server_set = []
if identifier
if identifier
if server = self.data[:servers][identifier]
server_set << server
else
@ -44,7 +44,7 @@ module Fog
else
server_set = self.data[:servers].values
end
server_set.each do |server|
case server["DBInstanceStatus"]
when "creating"
@ -78,10 +78,10 @@ module Fog
if server["PendingModifiedValues"]
server["DBInstanceStatus"] = 'modifying'
end
end
end
end
response.status = 200
response.body = {
"ResponseMetadata"=>{ "RequestId"=> Fog::AWS::Mock.request_id },
@ -89,7 +89,7 @@ module Fog
}
response
end
end
end

View file

@ -5,7 +5,7 @@ module Fog
require 'fog/aws/parsers/rds/describe_db_security_groups'
# Describe all or specified db snapshots
# Describe all or specified db security groups
# http://docs.amazonwebservices.com/AmazonRDS/latest/APIReference/index.html?API_DescribeDBSecurityGroups.html
# ==== Parameters
# * DBSecurityGroupName <~String> - The name of the DB Security Group to return details for.
@ -28,11 +28,11 @@ module Fog
class Mock
def describe_db_security_groups(opts={})
def describe_db_security_groups(opts={})
response = Excon::Response.new
sec_group_set = []
if opts.is_a?(String)
sec_group_name = opts
sec_group_name = opts
if sec_group = self.data[:security_groups][sec_group_name]
sec_group_set << sec_group
else
@ -41,7 +41,9 @@ module Fog
else
sec_group_set = self.data[:security_groups].values
end
# TODO: refactor to not delete items that we're iterating over. Causes
# model tests to fail (currently pending)
sec_group_set.each do |sec_group|
sec_group["IPRanges"].each do |iprange|
if iprange["Status"] == "authorizing" || iprange["Status"] == "revoking"
@ -53,7 +55,9 @@ module Fog
end
end
end
# TODO: refactor to not delete items that we're iterating over. Causes
# model tests to fail (currently pending)
sec_group["EC2SecurityGroups"].each do |ec2_secg|
if ec2_secg["Status"] == "authorizing" || iprange["Status"] == "revoking"
ec2_secg[:tmp] ||= Time.now + Fog::Mock.delay * 2
@ -65,7 +69,7 @@ module Fog
end
end
end
response.status = 200
response.body = {
"ResponseMetadata"=>{ "RequestId"=> Fog::AWS::Mock.request_id },

View file

@ -33,7 +33,34 @@ module Fog
class Mock
def describe_db_snapshots(opts={})
Fog::Mock.not_implemented
response = Excon::Response.new
snapshots = self.data[:snapshots].values
if opts[:identifier]
snapshots = snapshots.select{|snapshot| snapshot['DBInstanceIdentifier'] == opts[:identifier]}
end
if opts[:snapshot_id]
snapshots = snapshots.select{|snapshot| snapshot['DBSnapshotIdentifier'] == opts[:snapshot_id]}
raise Fog::AWS::RDS::NotFound.new("DBSnapshot #{opts[:snapshot_id]} not found") if snapshots.empty?
end
snapshots.each do |snapshot|
case snapshot['Status']
when 'creating'
if Time.now - snapshot['SnapshotCreateTime'] > Fog::Mock.delay
snapshot['Status'] = 'available'
end
end
end
# Build response
response.status = 200
response.body = {
"ResponseMetadata"=>{ "RequestId"=> Fog::AWS::Mock.request_id },
"DescribeDBSnapshotsResult" => { "DBSnapshots" => snapshots }
}
response
end
end

View file

@ -2,8 +2,7 @@ Shindo.tests("AWS::RDS | security_group", ['aws', 'rds']) do
group_name = 'fog-test'
params = {:id => group_name, :description => 'fog test'}
pending if Fog.mocking?
model_tests(Fog::AWS[:rds].security_groups, params, false) do
model_tests(Fog::AWS[:rds].security_groups, params) do
tests("#description").returns('fog test') { @instance.description }
@ -19,6 +18,8 @@ Shindo.tests("AWS::RDS | security_group", ['aws', 'rds']) do
@instance.wait_for { ready? }
tests("#revoke_ec2_security_group").succeeds do
pending if Fog.mocking?
@instance.revoke_ec2_security_group(@ec2_sec_group.name)
returns('revoking') do
@ -37,8 +38,10 @@ Shindo.tests("AWS::RDS | security_group", ['aws', 'rds']) do
returns('authorizing') { @instance.ip_ranges.detect{|h| h['CIDRIP'] == @cidr}['Status'] }
end
@instance.wait_for { ready? }
tests("#revoke_cidrip").succeeds do
pending if Fog.mocking?
@instance.wait_for { ready? }
@instance.revoke_cidrip(@cidr)
returns('revoking') { @instance.ip_ranges.detect{|h| h['CIDRIP'] == @cidr}['Status'] }
@instance.wait_for { ready? }

View file

@ -1,6 +1,5 @@
Shindo.tests("AWS::RDS | security groups", ['aws', 'rds']) do
params = {:id => 'fog-test', :description => 'fog test'}
pending if Fog.mocking?
collection_tests(Fog::AWS[:rds].security_groups, params, false)
collection_tests(Fog::AWS[:rds].security_groups, params)
end

View file

@ -1,8 +1,6 @@
Shindo.tests("AWS::RDS | server", ['aws', 'rds']) do
pending if Fog.mocking?
model_tests(Fog::AWS[:rds].servers, rds_default_server_params, false) do
model_tests(Fog::AWS[:rds].servers, rds_default_server_params) do
# We'll need this later; create it early to avoid waiting
@instance_with_final_snapshot = Fog::AWS[:rds].servers.create(rds_default_server_params.merge(:id => uniq_id("fog-snapshot-test"), :backup_retention_period => 1))
@ -25,6 +23,8 @@ Shindo.tests("AWS::RDS | server", ['aws', 'rds']) do
end
tests("#modify").succeeds do
pending if Fog.mocking?
orig_parameter_group = @instance.db_parameter_groups.first['DBParameterGroupName']
parameter_group = Fog::AWS[:rds].parameter_groups.create(:id => uniq_id, :family => 'mysql5.1', :description => 'fog-test')
@ -77,6 +77,8 @@ Shindo.tests("AWS::RDS | server", ['aws', 'rds']) do
@instance.reload.wait_for { ready? }
tests('#create_read_replica').succeeds do
pending if Fog.mocking?
replica = @instance_with_final_snapshot.create_read_replica(uniq_id('fog-replica'))
@instance_with_final_snapshot.reload
returns([replica.id]) { @instance_with_final_snapshot.read_replica_identifiers }

View file

@ -1,8 +1,6 @@
Shindo.tests("AWS::RDS | servers", ['aws', 'rds']) do
pending if Fog.mocking?
collection_tests(Fog::AWS[:rds].servers, rds_default_server_params, false) do
collection_tests(Fog::AWS[:rds].servers, rds_default_server_params) do
@instance.wait_for { ready? }
end
end

View file

@ -1,12 +1,10 @@
Shindo.tests("AWS::RDS | snapshot", ['aws', 'rds']) do
pending if Fog.mocking?
@server = Fog::AWS[:rds].servers.create(rds_default_server_params)
@server.wait_for { ready? }
params = {:id => uniq_id, :instance_id => @server.id}
model_tests(Fog::AWS[:rds].snapshots, params, false) do
model_tests(Fog::AWS[:rds].snapshots, params) do
@instance.wait_for { ready? }
end

View file

@ -1,12 +1,10 @@
Shindo.tests("AWS::RDS | snapshots", ['aws', 'rds']) do
pending if Fog.mocking?
@server = Fog::AWS[:rds].servers.create(rds_default_server_params)
@server.wait_for { ready? }
params = {:id => uniq_id, :instance_id => @server.id}
collection_tests(Fog::AWS[:rds].snapshots, params, false) do
collection_tests(Fog::AWS[:rds].snapshots, params) do
@instance.wait_for { ready? }
end

View file

@ -7,7 +7,7 @@ class AWS
BASIC = {
'ResponseMetadata' => {'RequestId' => String}
}
DB_PARAMETER_GROUP = {
'DBParameterGroupFamily' => String,
'DBParameterGroupName'=> String,
@ -15,11 +15,11 @@ class AWS
}
CREATE_DB_PARAMETER_GROUP = {
'ResponseMetadata' => {'RequestId' => String},
'CreateDBParameterGroupResult' => {
'CreateDBParameterGroupResult' => {
'DBParameterGroup' => DB_PARAMETER_GROUP
}
}
DB_SECURITY_GROUP = {
'DBSecurityGroupDescription' => String,
'DBSecurityGroupName' => String,
@ -27,46 +27,45 @@ class AWS
'IPRanges' => [Fog::Nullable::Hash],
'OwnerId' => Fog::Nullable::String
}
CREATE_DB_SECURITY_GROUP = BASIC.merge({
'CreateDBSecurityGroupResult' => {
'DBSecurityGroup' => DB_SECURITY_GROUP
'CreateDBSecurityGroupResult' => {
'DBSecurityGroup' => DB_SECURITY_GROUP
}
})
AUTHORIZE_DB_SECURITY_GROUP = BASIC.merge({
'AuthorizeDBSecurityGroupIngressResult' => {
'AuthorizeDBSecurityGroupIngressResult' => {
'DBSecurityGroup' => DB_SECURITY_GROUP
}
})
REVOKE_DB_SECURITY_GROUP = BASIC.merge({
'RevokeDBSecurityGroupIngressResult' => {
'RevokeDBSecurityGroupIngressResult' => {
'DBSecurityGroup' => DB_SECURITY_GROUP
}
})
DESCRIBE_DB_SECURITY_GROUP = BASIC.merge({
'DescribeDBSecurityGroupsResult' => {
'DescribeDBSecurityGroupsResult' => {
'DBSecurityGroups' => [DB_SECURITY_GROUP]
}
})
DESCRIBE_DB_PARAMETER_GROUP = {
'ResponseMetadata' => {'RequestId' => String},
'DescribeDBParameterGroupsResult' =>{
'DBParameterGroups' => [DB_PARAMETER_GROUP]
}
}
MODIFY_PARAMETER_GROUP = BASIC.merge({
'ModifyDBParameterGroupResult' => {
'DBParameterGroupName' => String
}
})
DB_PARAMETER = {
'ParameterValue' => Fog::Nullable::String,
'DataType' => String,
@ -77,15 +76,15 @@ class AWS
'ParameterName' => String,
'ApplyType' => String
}
DESCRIBE_DB_PARAMETERS = BASIC.merge({
'DescribeDBParametersResult' => {
'Marker' => Fog::Nullable::String,
'Parameters' => [DB_PARAMETER]
}
})
SNAPSHOT={
'AllocatedStorage' => Integer,
'AvailabilityZone' => String,
@ -142,7 +141,7 @@ class AWS
'ReadReplicaDBInstanceIdentifiers'=> [Fog::Nullable::String],
'ReadReplicaSourceDBInstanceIdentifier'=> Fog::Nullable::String
}
CREATE_DB_INSTANCE = BASIC.merge({
'CreateDBInstanceResult' => {
'DBInstance' => INSTANCE
@ -167,13 +166,13 @@ class AWS
'DBInstance' => INSTANCE
}
})
REBOOT_DB_INSTANCE = BASIC.merge({
'RebootDBInstanceResult' => {
'DBInstance' => INSTANCE
}
})
CREATE_READ_REPLICA = BASIC.merge({
'CreateDBInstanceReadReplicaResult' => {
'DBInstance' => INSTANCE

View file

@ -10,7 +10,6 @@ Shindo.tests('AWS::RDS | instance requests', ['aws', 'rds']) do
@db_final_snapshot_id = "fog-final-snapshot"
tests('success') do
#
tests("#create_db_instance").formats(AWS::RDS::Formats::CREATE_DB_INSTANCE) do
result = Fog::AWS[:rds].create_db_instance(@db_instance_id, 'AllocatedStorage' => 5,
@ -59,8 +58,6 @@ Shindo.tests('AWS::RDS | instance requests', ['aws', 'rds']) do
server.reload.wait_for { state == 'rebooting' }
server.reload.wait_for { state == 'available'}
pending if Fog.mocking?
tests("#create_db_snapshot").formats(AWS::RDS::Formats::CREATE_DB_SNAPSHOT) do
body = Fog::AWS[:rds].create_db_snapshot(@db_instance_id, @db_snapshot_id).body
returns('creating'){ body['CreateDBSnapshotResult']['DBSnapshot']['Status']}
@ -73,6 +70,8 @@ Shindo.tests('AWS::RDS | instance requests', ['aws', 'rds']) do
server.reload.wait_for { state == 'available' }
pending if Fog.mocking?
tests( "#create read replica").formats(AWS::RDS::Formats::CREATE_READ_REPLICA) do
Fog::AWS[:rds].create_db_instance_read_replica(@db_replica_id, @db_instance_id).body
end
@ -115,8 +114,6 @@ Shindo.tests('AWS::RDS | instance requests', ['aws', 'rds']) do
end
tests('failure') do
pending if Fog.mocking?
tests "deleting nonexisting instance" do
raises(Fog::AWS::RDS::NotFound) {Fog::AWS[:rds].delete_db_instance('doesnexist', 'irrelevant')}
end