Add pretend networking and interface association to the network interface mocking

This commit is contained in:
Eric Herot 2014-02-18 12:46:43 -05:00
parent 911ec7c5a8
commit 421bc0adb7
9 changed files with 200 additions and 64 deletions

View File

@ -44,10 +44,14 @@ Gem::Specification.new do |s|
s.add_dependency("fog-core", "~> 1.21", ">= 1.21.1")
s.add_dependency("fog-json")
s.add_dependency('nokogiri', '~> 1.5', '>= 1.5.11')
# Modular providers
s.add_dependency("fog-brightbox")
s.add_dependency('builder')
s.add_dependency('excon', '~>0.31.0')
s.add_dependency('formatador', '~>0.2.0')
s.add_dependency('ipaddress', '~>0.5')
s.add_dependency('mime-types')
s.add_dependency('net-scp', '~>1.1')
s.add_dependency('net-ssh', '>=2.1.3')
s.add_dependency('nokogiri', '>=1.5.11')
## List your development dependencies here. Development dependencies are
## those that are only needed during development

View File

@ -35,10 +35,17 @@ module Fog
def attach_network_interface(nic_id, instance_id, device_index)
response = Excon::Response.new
if self.data[:network_interfaces][nic_id]
if ! self.data[:instances].find{ |i,i_conf|
i_conf['instanceId'] == instance_id
}
raise Fog::Compute::AWS::NotFound.new("The instance ID '#{instance_id}' does not exist")
elsif self.data[:network_interfaces].find{ |ni,ni_conf| ni_conf['attachment']['instanceId'] == instance_id && ni_conf['attachment']['deviceIndex'] == device_index }
raise Fog::Compute::AWS::Error.new("InvalidParameterValue => Instance '#{instance_id}' already has an interface attached at device index '#{device_index}'.")
elsif self.data[:network_interfaces][nic_id]
attachment = self.data[:network_interfaces][nic_id]['attachment']
attachment['attachmentId'] = Fog::AWS::Mock.request_id
attachment['instanceId'] = instance_id
attachment['deviceIndex'] = device_index
response.status = 200
response.body = {

View File

@ -65,45 +65,63 @@ module Fog
def create_network_interface(subnetId, options = {})
response = Excon::Response.new
if subnetId
id = Fog::AWS::Mock.network_interface_id
subnet = self.data[:subnets].find{ |s| s['subnetId'] == subnetId }
if subnet.nil?
raise Fog::Compute::AWS::Error.new("Unknown subnet '#{subnetId}' specified")
else
id = Fog::AWS::Mock.network_interface_id
cidr_block = IPAddress.parse(subnet['cidrBlock'])
groups = {}
if options['GroupSet']
options['GroupSet'].each do |group_id|
name = self.data[:security_groups].select { |k,v| v['groupId'] == group_id }.first
if name.nil?
raise Fog::Compute::AWS::Error.new("Unknown security group '#{group_id}' specified")
groups = {}
if options['GroupSet']
options['GroupSet'].each do |group_id|
name = self.data[:security_groups].select { |k,v| v['groupId'] == group_id } .first.first
if name.nil?
raise Fog::Compute::AWS::Error.new("Unknown security group '#{group_id}' specified")
end
groups[group_id] = name
end
groups[group_id] = name
end
end
if options['PrivateIpAddress'].nil?
options['PrivateIpAddress'] = "10.0.0.2"
end
data = {
'networkInterfaceId' => id,
'subnetId' => subnetId,
'vpcId' => 'mock-vpc-id',
'availabilityZone' => 'mock-zone',
'description' => options['Description'],
'ownerId' => '',
'requesterManaged' => 'false',
'status' => 'available',
'macAddress' => '00:11:22:33:44:55',
'privateIpAddress' => options['PrivateIpAddress'],
'sourceDestCheck' => true,
'groupSet' => groups,
'attachment' => {},
'association' => {},
'tagSet' => {}
}
self.data[:network_interfaces][id] = data
response.body = {
'requestId' => Fog::AWS::Mock.request_id,
'networkInterface' => data
}
response
if options['PrivateIpAddress'].nil?
# Here we try to act like a DHCP server and pick the first
# available IP (not including the first in the cidr block,
# which is typically reserved for the gateway).
cidr_block.each_host do |p_ip|
unless self.data[:network_interfaces].map{ |ni, ni_conf| ni_conf['privateIpAddress'] }.include?p_ip.to_s ||
cidr_block.first == p_ip
options['PrivateIpAddress'] = p_ip.to_s
break
end
end
elsif self.data[:network_interfaces].map{ |ni,ni_conf| ni_conf['privateIpAddress'] }.include?options['PrivateIpAddress']
raise Fog::Compute::AWS::Error.new("InUse => The specified address is already in use.")
end
data = {
'networkInterfaceId' => id,
'subnetId' => subnetId,
'vpcId' => 'mock-vpc-id',
'availabilityZone' => 'mock-zone',
'description' => options['Description'],
'ownerId' => '',
'requesterManaged' => 'false',
'status' => 'available',
'macAddress' => '00:11:22:33:44:55',
'privateIpAddress' => options['PrivateIpAddress'],
'sourceDestCheck' => true,
'groupSet' => groups,
'attachment' => {},
'association' => {},
'tagSet' => {}
}
self.data[:network_interfaces][id] = data
response.body = {
'requestId' => Fog::AWS::Mock.request_id,
'networkInterface' => data
}
response
end
else
response.status = 400
response.body = {

View File

@ -3,6 +3,7 @@ module Fog
class AWS
class Real
require 'ipaddress'
require 'fog/aws/parsers/compute/create_subnet'
# Creates a Subnet with the CIDR block you specify.
@ -44,7 +45,20 @@ module Fog
def create_subnet(vpcId, cidrBlock, options = {})
av_zone = options['AvailabilityZone'].nil? ? 'us-east-1c' : options['AvailabilityZone']
Excon::Response.new.tap do |response|
if cidrBlock && vpcId
if cidrBlock && vpcId
vpc = self.data[:vpcs].find{ |v| v['vpcId'] == vpcId }
if vpc.nil?
raise Fog::Compute::AWS::NotFound.new("The vpc ID '#{vpcId}' does not exist")
end
if ! ::IPAddress.parse(vpc['cidrBlock']).include?(::IPAddress.parse(cidrBlock))
raise Fog::Compute::AWS::Error.new("Range => The CIDR '#{cidrBlock}' is invalid.")
end
self.data[:subnets].each do |subnet|
if ::IPAddress.parse(subnet['cidrBlock']).include?(::IPAddress.parse(cidrBlock))
raise Fog::Compute::AWS::Error.new("Conflict => The CIDR '#{cidrBlock}' conflicts with another subnet")
end
end
response.status = 200
data = {
'subnetId' => Fog::AWS::Mock.subnet_id,

View File

@ -184,8 +184,6 @@ module Fog
instance['ipAddress'] = Fog::AWS::Mock.ip_address
instance['originalIpAddress'] = instance['ipAddress']
instance['dnsName'] = Fog::AWS::Mock.dns_name_for(instance['ipAddress'])
instance['privateIpAddress'] = Fog::AWS::Mock.private_ip_address
instance['privateDnsName'] = Fog::AWS::Mock.private_dns_name_for(instance['privateIpAddress'])
instance['instanceState'] = { 'code' => 16, 'name' => 'running' }
end
when 'rebooting'
@ -209,18 +207,30 @@ module Fog
if self.data[:instances][instance['instanceId']]
instance['networkInterfaces'] = self.data[:network_interfaces].select{|ni,ni_conf|
ni_conf['attachment']['instanceId'] == instance['instanceId']
}.map{|ni,ni_conf|
{
'ownerId' => ni_conf['ownerId'],
'subnetId' => ni_conf['subnetId'],
'vpcId' => ni_conf['vpcId'],
'networkInterfaceId' => ni_conf['networkInterfaceId'],
'groupSet' => ni_conf['groupSet'],
'attachmentId' => ni_conf['attachment']['attachmentId']
}
nics = self.data[:network_interfaces].select{|ni,ni_conf|
ni_conf['attachment']['instanceId'] == instance['instanceId']
}
instance['networkInterfaces'] = nics.map{|ni,ni_conf|
{
'ownerId' => ni_conf['ownerId'],
'subnetId' => ni_conf['subnetId'],
'vpcId' => ni_conf['vpcId'],
'networkInterfaceId' => ni_conf['networkInterfaceId'],
'groupSet' => ni_conf['groupSet'],
'attachmentId' => ni_conf['attachment']['attachmentId']
}
}
if nics.count > 0
instance['privateIpAddress'] = nics.sort_by {|ni, ni_conf|
ni_conf['attachment']['deviceIndex']
}.map{ |ni, ni_conf| ni_conf['privateIpAddress'] }.first
instance['privateDnsName'] = Fog::AWS::Mock.private_dns_name_for(instance['privateIpAddress'])
else
instance['privateIpAddress'] = ''
instance['privateDnsName'] = ''
end
reservation_set[instance['reservationId']] ||= {
'groupSet' => instance['groupSet'],

View File

@ -184,6 +184,16 @@ module Fog
}
end
if options['SubnetId']
if options['PrivateIpAddress']
ni_options = {'PrivateIpAddress' => options['PrivateIpAddress']}
else
ni_options = {}
end
network_interface_id = create_network_interface(options['SubnetId'], ni_options).body['networkInterface']['networkInterfaceId']
end
network_interfaces = (options['NetworkInterfaces'] || []).inject([]) do |mapping, device|
device_index = device.fetch("DeviceIndex", 0)
subnet_id = device.fetch("SubnetId", options[:subnet_id] || Fog::AWS::Mock.subnet_id)
@ -238,12 +248,15 @@ module Fog
'groupIds' => [],
'groupSet' => group_set,
'iamInstanceProfile' => {},
'networkInterfaces' => [],
'ownerId' => self.data[:owner_id],
'privateIpAddress' => nil,
'reservationId' => reservation_id,
'stateReason' => {}
})
if options['SubnetId']
attachment_id = attach_network_interface(network_interface_id, instance_id, 0).data[:body]['attachmentId']
modify_network_interface_attribute(network_interface_id, 'attachment', {'attachmentId' => attachment_id, 'deleteOnTermination' => 'true'})
end
end
response.body = {
'groupSet' => group_set,

View File

@ -204,11 +204,15 @@ Shindo.tests('Fog::Compute[:aws] | instance requests', ['aws']) do
# Test network interface attachment
tests('#describe_instances networkInterfaces') do
data = Fog::Compute[:aws].create_network_interface('subnet-12345678').body
vpc = Fog::Compute[:aws].vpcs.create('cidr_block' => '10.0.10.0/16')
subnet = Fog::Compute[:aws].subnets.create('vpc_id' => vpc.id, 'cidr_block' => '10.0.10.0/16')
data = Fog::Compute[:aws].create_network_interface(subnet.subnet_id).body
@network_interface_id = data['networkInterface']['networkInterfaceId']
Fog::Compute[:aws].attach_network_interface(@network_interface_id, @instance_id, 1)
Fog::Compute[:aws].attach_network_interface(@network_interface_id, @instance_id, '1')
body = Fog::Compute[:aws].describe_instances('instance-id' => "#{@instance_id}").body
tests("returns 1 attachment").returns(1) { body['reservationSet'].first['instancesSet'].first['networkInterfaces'].size }
subnet.destroy
vpc.destroy
end
another_server.destroy
@ -269,6 +273,9 @@ Shindo.tests('Fog::Compute[:aws] | instance requests', ['aws']) do
tests('failure') do
tests("#run_instances(nil, 1, 1, {'SubnetId'=>'subnet-00000000'}").raises(::Fog::Compute::AWS::Error) do
Fog::Compute[:aws].run_instances(nil, 1, 1, {'SubnetId' => 'subnet-000000'})
end
tests("#get_console_output('i-00000000')").raises(Fog::Compute::AWS::NotFound) do
Fog::Compute[:aws].get_console_output('i-00000000')
end

View File

@ -120,11 +120,12 @@ Shindo.tests('Fog::Compute[:aws] | network interface requests', ['aws']) do
@server = Fog::Compute[:aws].servers.create({:flavor_id => 'm1.small', :subnet_id => @subnet_id })
@server.wait_for { ready? }
@instance_id=@server.id
@instance_id=@server.id
# attach
# attach
@device_index = 1
tests('#attach_network_interface').formats(@attach_network_interface_format) do
data = Fog::Compute[:aws].attach_network_interface(@nic_id, @instance_id, 1).body
data = Fog::Compute[:aws].attach_network_interface(@nic_id, @instance_id, @device_index).body
@attachment_id = data['attachmentId']
data
end
@ -201,4 +202,48 @@ Shindo.tests('Fog::Compute[:aws] | network interface requests', ['aws']) do
@subnet.destroy
@vpc.destroy
end
tests('failure') do
# Attempt to attach a nonexistent interface
tests("#attach_network_interface('eni-00000000', 'i-00000000', '1')").raises(::Fog::Compute::AWS::NotFound) do
Fog::Compute[:aws].attach_network_interface('eni-00000000', 'i-00000000', '1')
end
# Create environment
@vpc = Fog::Compute[:aws].vpcs.create('cidr_block' => '10.0.10.0/24')
@subnet = Fog::Compute[:aws].subnets.create('vpc_id' => @vpc.id, 'cidr_block' => '10.0.10.16/28')
@subnet_id = @subnet.subnet_id
data = Fog::Compute[:aws].create_network_interface(@subnet_id).body
@nic_id = data['networkInterface']['networkInterfaceId']
# Attempt to re-use an existing IP for another ENI
tests("#create_network_interface('#{@subnet_id}', {'PrivateIpAddress' => '#{data['networkInterface']['privateIpAddress']}'}").raises(::Fog::Compute::AWS::Error) do
Fog::Compute[:aws].create_network_interface(@subnet_id, {'PrivateIpAddress' => data['networkInterface']['privateIpAddress']})
end
# Attempt to attach a valid ENI to a nonexistent instance.
tests("#attach_network_interface('#{@nic_id}', 'i-00000000', '0')").raises(::Fog::Compute::AWS::NotFound) do
Fog::Compute[:aws].attach_network_interface(@nic_id, 'i-00000000', '0')
end
@server = Fog::Compute[:aws].servers.create({:flavor_id => 'm1.small', :subnet_id => @subnet_id })
@server.wait_for { ready? }
@instance_id=@server.id
@device_index = 1
data = Fog::Compute[:aws].attach_network_interface(@nic_id, @instance_id, @device_index).body
# Attempt to attach two ENIs to the same instance with the same device
# index.
tests("#attach_network_interface('#{@nic_id}', '#{@instance_id}', '#{@device_index}')").raises(::Fog::Compute::AWS::Error) do
Fog::Compute[:aws].attach_network_interface(@nic_id, @instance_id, @device_index)
end
@server.destroy
@subnet.destroy
@vpc.destroy
end
end

View File

@ -20,9 +20,10 @@ Shindo.tests('Fog::Compute[:aws] | subnet requests', ['aws']) do
'requestId' => String
}
@vpc=Fog::Compute[:aws].vpcs.create('cidr_block' => '10.0.10.0/24')
@vpc_id = @vpc.id
tests('success') do
@vpc=Fog::Compute[:aws].vpcs.create('cidr_block' => '10.0.10.0/24')
@vpc_id = @vpc.id
@subnet_id = nil
tests('#create_subnet').formats(@single_subnet_format) do
@ -38,6 +39,23 @@ Shindo.tests('Fog::Compute[:aws] | subnet requests', ['aws']) do
tests("#delete_subnet('#{@subnet_id}')").formats(AWS::Compute::Formats::BASIC) do
Fog::Compute[:aws].delete_subnet(@subnet_id).body
end
@vpc.destroy
end
tests('failure') do
tests("#create_subnet('vpc-00000000', '10.0.10.0/16')").raises(Fog::Compute::AWS::NotFound) do
Fog::Compute[:aws].create_subnet('vpc-00000000', '10.0.10.0/16')
end
tests("#create_subnet('#{@vpc_id}', '10.0.9.16/28')").raises(Fog::Compute::AWS::Error) do
Fog::Compute[:aws].create_subnet(@vpc_id, '10.0.9.16/28')
end
# Attempt to create two subnets with conflicting CIDRs
tests("#create_subnet('#{@vpc_id}', '10.0.10.64/26')").raises(::Fog::Compute::AWS::Error) do
Fog::Compute[:aws].create_subnet(@vpc_id, '10.0.10.0/24')
Fog::Compute[:aws].create_subnet(@vpc_id, '10.0.10.64/26')
end
end
@vpc.destroy
end