Class: Fog::AWS::Compute::Mock

Inherits:
Object
  • Object
show all
Includes:
Fog::AWS::CredentialFetcher::ConnectionMethods
Defined in:
lib/fog/aws/compute.rb,
lib/fog/aws/requests/compute/copy_image.rb,
lib/fog/aws/requests/compute/create_vpc.rb,
lib/fog/aws/requests/compute/delete_vpc.rb,
lib/fog/aws/requests/compute/create_tags.rb,
lib/fog/aws/requests/compute/delete_tags.rb,
lib/fog/aws/requests/compute/create_image.rb,
lib/fog/aws/requests/compute/create_route.rb,
lib/fog/aws/requests/compute/delete_route.rb,
lib/fog/aws/requests/compute/attach_volume.rb,
lib/fog/aws/requests/compute/copy_snapshot.rb,
lib/fog/aws/requests/compute/create_subnet.rb,
lib/fog/aws/requests/compute/create_volume.rb,
lib/fog/aws/requests/compute/delete_subnet.rb,
lib/fog/aws/requests/compute/delete_volume.rb,
lib/fog/aws/requests/compute/describe_tags.rb,
lib/fog/aws/requests/compute/describe_vpcs.rb,
lib/fog/aws/requests/compute/detach_volume.rb,
lib/fog/aws/requests/compute/modify_volume.rb,
lib/fog/aws/requests/compute/replace_route.rb,
lib/fog/aws/requests/compute/run_instances.rb,
lib/fog/aws/requests/compute/register_image.rb,
lib/fog/aws/requests/compute/stop_instances.rb,
lib/fog/aws/requests/compute/create_key_pair.rb,
lib/fog/aws/requests/compute/create_snapshot.rb,
lib/fog/aws/requests/compute/delete_key_pair.rb,
lib/fog/aws/requests/compute/delete_snapshot.rb,
lib/fog/aws/requests/compute/describe_images.rb,
lib/fog/aws/requests/compute/import_key_pair.rb,
lib/fog/aws/requests/compute/release_address.rb,
lib/fog/aws/requests/compute/start_instances.rb,
lib/fog/aws/requests/compute/allocate_address.rb,
lib/fog/aws/requests/compute/deregister_image.rb,
lib/fog/aws/requests/compute/describe_regions.rb,
lib/fog/aws/requests/compute/describe_subnets.rb,
lib/fog/aws/requests/compute/describe_volumes.rb,
lib/fog/aws/requests/compute/reboot_instances.rb,
lib/fog/aws/requests/compute/associate_address.rb,
lib/fog/aws/requests/compute/get_password_data.rb,
lib/fog/aws/requests/compute/monitor_instances.rb,
lib/fog/aws/requests/compute/create_network_acl.rb,
lib/fog/aws/requests/compute/create_route_table.rb,
lib/fog/aws/requests/compute/delete_network_acl.rb,
lib/fog/aws/requests/compute/delete_route_table.rb,
lib/fog/aws/requests/compute/describe_addresses.rb,
lib/fog/aws/requests/compute/describe_instances.rb,
lib/fog/aws/requests/compute/describe_key_pairs.rb,
lib/fog/aws/requests/compute/describe_snapshots.rb,
lib/fog/aws/requests/compute/get_console_output.rb,
lib/fog/aws/requests/compute/create_dhcp_options.rb,
lib/fog/aws/requests/compute/delete_dhcp_options.rb,
lib/fog/aws/requests/compute/move_address_to_vpc.rb,
lib/fog/aws/requests/compute/terminate_instances.rb,
lib/fog/aws/requests/compute/unmonitor_instances.rb,
lib/fog/aws/requests/compute/disassociate_address.rb,
lib/fog/aws/requests/compute/modify_vpc_attribute.rb,
lib/fog/aws/requests/compute/associate_route_table.rb,
lib/fog/aws/requests/compute/create_security_group.rb,
lib/fog/aws/requests/compute/delete_security_group.rb,
lib/fog/aws/requests/compute/describe_dhcp_options.rb,
lib/fog/aws/requests/compute/describe_network_acls.rb,
lib/fog/aws/requests/compute/describe_route_tables.rb,
lib/fog/aws/requests/compute/associate_dhcp_options.rb,
lib/fog/aws/requests/compute/describe_volume_status.rb,
lib/fog/aws/requests/compute/describe_vpc_attribute.rb,
lib/fog/aws/requests/compute/modify_image_attribute.rb,
lib/fog/aws/requests/compute/request_spot_instances.rb,
lib/fog/aws/requests/compute/attach_classic_link_vpc.rb,
lib/fog/aws/requests/compute/attach_internet_gateway.rb,
lib/fog/aws/requests/compute/create_internet_gateway.rb,
lib/fog/aws/requests/compute/delete_internet_gateway.rb,
lib/fog/aws/requests/compute/detach_classic_link_vpc.rb,
lib/fog/aws/requests/compute/detach_internet_gateway.rb,
lib/fog/aws/requests/compute/enable_vpc_classic_link.rb,
lib/fog/aws/requests/compute/modify_subnet_attribute.rb,
lib/fog/aws/requests/compute/modify_volume_attribute.rb,
lib/fog/aws/requests/compute/attach_network_interface.rb,
lib/fog/aws/requests/compute/create_network_acl_entry.rb,
lib/fog/aws/requests/compute/create_network_interface.rb,
lib/fog/aws/requests/compute/delete_network_acl_entry.rb,
lib/fog/aws/requests/compute/delete_network_interface.rb,
lib/fog/aws/requests/compute/describe_image_attribute.rb,
lib/fog/aws/requests/compute/describe_instance_status.rb,
lib/fog/aws/requests/compute/describe_security_groups.rb,
lib/fog/aws/requests/compute/detach_network_interface.rb,
lib/fog/aws/requests/compute/disable_vpc_classic_link.rb,
lib/fog/aws/requests/compute/disassociate_route_table.rb,
lib/fog/aws/requests/compute/describe_vpc_classic_link.rb,
lib/fog/aws/requests/compute/replace_network_acl_entry.rb,
lib/fog/aws/requests/compute/describe_internet_gateways.rb,
lib/fog/aws/requests/compute/restore_address_to_classic.rb,
lib/fog/aws/requests/compute/assign_private_ip_addresses.rb,
lib/fog/aws/requests/compute/describe_account_attributes.rb,
lib/fog/aws/requests/compute/describe_availability_zones.rb,
lib/fog/aws/requests/compute/describe_instance_attribute.rb,
lib/fog/aws/requests/compute/describe_network_interfaces.rb,
lib/fog/aws/requests/compute/describe_reserved_instances.rb,
lib/fog/aws/requests/compute/describe_spot_price_history.rb,
lib/fog/aws/requests/compute/revoke_security_group_egress.rb,
lib/fog/aws/requests/compute/cancel_spot_instance_requests.rb,
lib/fog/aws/requests/compute/revoke_security_group_ingress.rb,
lib/fog/aws/requests/compute/describe_volumes_modifications.rb,
lib/fog/aws/requests/compute/authorize_security_group_egress.rb,
lib/fog/aws/requests/compute/describe_classic_link_instances.rb,
lib/fog/aws/requests/compute/describe_spot_instance_requests.rb,
lib/fog/aws/requests/compute/replace_network_acl_association.rb,
lib/fog/aws/requests/compute/authorize_security_group_ingress.rb,
lib/fog/aws/requests/compute/reset_network_interface_attribute.rb,
lib/fog/aws/requests/compute/modify_network_interface_attribute.rb,
lib/fog/aws/requests/compute/enable_vpc_classic_link_dns_support.rb,
lib/fog/aws/requests/compute/describe_network_interface_attribute.rb,
lib/fog/aws/requests/compute/disable_vpc_classic_link_dns_support.rb,
lib/fog/aws/requests/compute/purchase_reserved_instances_offering.rb,
lib/fog/aws/requests/compute/describe_reserved_instances_offerings.rb,
lib/fog/aws/requests/compute/describe_vpc_classic_link_dns_support.rb

Constant Summary collapse

MOCKED_TAG_TYPES =
{
  'acl'  => 'network_acl',
  'ami'  => 'image',
  'igw'  => 'internet_gateway',
  'i'    => 'instance',
  'rtb'  => 'route_table',
  'snap' => 'snapshot',
  'vol'  => 'volume',
  'vpc'  => 'vpc'
}
VPC_BLANK_VALUE =
'none'

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Fog::AWS::CredentialFetcher::ConnectionMethods

#refresh_credentials_if_expired

Constructor Details

#initialize(options = {}) ⇒ Mock

Returns a new instance of Mock.



316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
# File 'lib/fog/aws/compute.rb', line 316

def initialize(options={})
  @use_iam_profile = options[:use_iam_profile]
  @aws_credentials_expire_at = Time::now + 20
  setup_credentials(options)
  @region = options[:region] || 'us-east-1'

  if @endpoint = options[:endpoint]
    endpoint = URI.parse(@endpoint)
    @host = endpoint.host or raise InvalidURIError.new("could not parse endpoint: #{@endpoint}")
    @path = endpoint.path
    @port = endpoint.port
    @scheme = endpoint.scheme
  else
    @host = options[:host] || "ec2.#{options[:region]}.amazonaws.com"
    @path       = options[:path]        || '/'
    @persistent = options[:persistent]  || false
    @port       = options[:port]        || 443
    @scheme     = options[:scheme]      || 'https'
  end
  Fog::AWS.validate_region!(@region, @host)
end

Instance Attribute Details

#regionObject

Returns the value of attribute region.



314
315
316
# File 'lib/fog/aws/compute.rb', line 314

def region
  @region
end

Class Method Details

.dataObject



205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
# File 'lib/fog/aws/compute.rb', line 205

def self.data
  @data ||= Hash.new do |hash, region|
    hash[region] = Hash.new do |region_hash, key|
      owner_id = Fog::AWS::Mock.owner_id
      security_group_id = Fog::AWS::Mock.security_group_id
      region_hash[key] = {
        :deleted_at => {},
        :addresses  => {},
        :images     => {},
        :image_launch_permissions => Hash.new do |permissions_hash, image_key|
          permissions_hash[image_key] = {
            :users => []
          }
        end,
        :instances  => {},
        :reserved_instances => {},
        :key_pairs  => {},
        :limits     => { :addresses => 5 },
        :owner_id   => owner_id,
        :security_groups => {
          'default' => {
            'groupDescription'    => 'default group',
            'groupName'           => 'default',
            'groupId'             => security_group_id,
            'ipPermissionsEgress' => [],
            'ipPermissions'       => [
              {
                'groups'      => [{'groupName' => 'default', 'userId' => owner_id, 'groupId' => security_group_id }],
                'fromPort'    => -1,
                'toPort'      => -1,
                'ipProtocol'  => 'icmp',
                'ipRanges'    => []
              },
              {
                'groups'      => [{'groupName' => 'default', 'userId' => owner_id, 'groupId' => security_group_id}],
                'fromPort'    => 0,
                'toPort'      => 65535,
                'ipProtocol'  => 'tcp',
                'ipRanges'    => []
              },
              {
                'groups'      => [{'groupName' => 'default', 'userId' => owner_id, 'groupId' => security_group_id}],
                'fromPort'    => 0,
                'toPort'      => 65535,
                'ipProtocol'  => 'udp',
                'ipRanges'    => []
              }
            ],
            'ownerId'             => owner_id
          },
          'amazon-elb-sg' => {
            'groupDescription'   => 'amazon-elb-sg',
            'groupName'          => 'amazon-elb-sg',
            'groupId'            => 'amazon-elb',
            'ownerId'            => 'amazon-elb',
            'ipPermissionsEgree' => [],
            'ipPermissions'      => [],
          },
        },
        :network_acls => {},
        :network_interfaces => {},
        :snapshots => {},
        :volumes => {},
        :internet_gateways => {},
        :tags => {},
        :tag_sets => Hash.new do |tag_set_hash, resource_id|
          tag_set_hash[resource_id] = {}
        end,
        :subnets => [],
        :vpcs => [],
        :dhcp_options => [],
        :route_tables => [],
        :account_attributes => [
          {
            "values"        => ["5"],
            "attributeName" => "vpc-max-security-groups-per-interface"
          },
          {
            "values"        => ["20"],
            "attributeName" => "max-instances"
          },
          {
            "values"        => ["EC2", "VPC"],
            "attributeName" => "supported-platforms"
          },
          {
            "values"        => [VPC_BLANK_VALUE],
            "attributeName" => "default-vpc"
          },
          {
            "values"        => ["5"],
            "attributeName" => "max-elastic-ips"
          },
          {
            "values"        => ["5"],
            "attributeName" => "vpc-max-elastic-ips"
          }
        ],
        :spot_requests => {},
        :volume_modifications => {}
      }
    end
  end
end

.resetObject



310
311
312
# File 'lib/fog/aws/compute.rb', line 310

def self.reset
  @data = nil
end

Instance Method Details

#allocate_address(domain = 'standard') ⇒ Object



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/fog/aws/requests/compute/allocate_address.rb', line 29

def allocate_address(domain = 'standard')
  unless describe_addresses.body['addressesSet'].size < self.data[:limits][:addresses]
    raise Fog::AWS::Compute::Error, "AddressLimitExceeded => Too many addresses allocated"
  end

  response = Excon::Response.new
  response.status = 200

  domain    = domain == 'vpc' ? 'vpc' : 'standard'
  public_ip = Fog::AWS::Mock.ip_address

  data = {
    'instanceId' => nil,
    'publicIp'   => public_ip,
    'domain'     => domain,
    :origin      => domain
  }

  if domain == 'vpc'
    data['allocationId'] = "eipalloc-#{Fog::Mock.random_hex(8)}"
  end

  self.data[:addresses][public_ip] = data
  response.body = data.reject {|k, v| k == 'instanceId' }.merge('requestId' => Fog::AWS::Mock.request_id)
  response
end

#apply_tag_filters(resources, filters, resource_id_key) ⇒ Object



492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
# File 'lib/fog/aws/compute.rb', line 492

def apply_tag_filters(resources, filters, resource_id_key)
  tag_set_fetcher = lambda {|resource| self.data[:tag_sets][resource[resource_id_key]] }

  # tag-key: match resources tagged with this key (any value)
  if filters.key?('tag-key')
    value = filters.delete('tag-key')
    resources = resources.select{|r| tag_set_fetcher[r].key?(value)}
  end

  # tag-value: match resources tagged with this value (any key)
  if filters.key?('tag-value')
    value = filters.delete('tag-value')
    resources = resources.select{|r| tag_set_fetcher[r].values.include?(value)}
  end

  # tag:key: match resources tagged with a key-value pair.  Value may be an array, which is OR'd.
  tag_filters = {}
  filters.keys.each do |key|
    tag_filters[key.gsub('tag:', '')] = filters.delete(key) if /^tag:/ =~ key
  end
  for tag_key, tag_value in tag_filters
    resources = resources.select{|r| [tag_value].flatten.include? tag_set_fetcher[r][tag_key]}
  end

  resources
end

#assign_private_ip_addresses(network_interface_id, options = {}) ⇒ Object



39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/fog/aws/requests/compute/assign_private_ip_addresses.rb', line 39

def assign_private_ip_addresses(network_interface_id, options={})
  if options['PrivateIpAddresses'] && options['SecondaryPrivateIpAddressCount']
    raise Fog::AWS::Compute::Error.new("You may specify secondaryPrivateIpAddressCount or specific secondary private IP addresses, but not both.")
  end

  response = Excon::Response.new
  response.status = 200
  response.body = {
    'requestId' => Fog::AWS::Mock.request_id,
    'return' => true
  }
  response
end

#associate_address(*args) ⇒ Object



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/fog/aws/requests/compute/associate_address.rb', line 57

def associate_address(*args)
  if args.first.kind_of? Hash
    params = args.first
  else
    params = {
        :instance_id => args[0],
        :public_ip => args[1],
        :network_interface_id => args[2],
        :allocation_id => args[3],
        :private_ip_address => args[4],
        :allow_reassociation => args[5],
    }
  end
  params[:public_ip] = params[:allocation_id].nil? ? params[:public_ip] : nil
  response = Excon::Response.new
  response.status = 200
  instance = self.data[:instances][params[:instance_id]]
 # address =  self.data[:addresses][params[:public_ip]]
  address = params[:public_ip].nil? ? nil : self.data[:addresses][params[:public_ip]]
  # This is a classic server, a VPC with a single network interface id or a VPC with multiple network interfaces one of which is specified
  if ((instance && address) || (instance &&  !params[:allocation_id].nil?) || (!params[:allocation_id].nil? && !network_interface_id.nil?))
    if !params[:allocation_id].nil?
      allocation_ip = describe_addresses( 'allocation-id'  => "#{params[:allocation_id]}").body['addressesSet'].first
      if !allocation_ip.nil?
        public_ip = allocation_ip['publicIp']
        address = public_ip.nil? ? nil : self.data[:addresses][public_ip]

        if instance['vpcId'] && vpc = self.data[:vpcs].detect { |v| v['vpcId'] == instance['vpcId'] }
          if vpc['enableDnsHostnames']
            instance['dnsName'] = Fog::AWS::Mock.dns_name_for(public_ip)
          end
        end
      end
    end
    if !address.nil?
      if current_instance = self.data[:instances][address['instanceId']]
        current_instance['ipAddress'] = current_instance['originalIpAddress']
      end
      address['instanceId'] = params[:instance_id]
    end
    # detach other address (if any)
    if self.data[:addresses][instance['ipAddress']]
      self.data[:addresses][instance['ipAddress']]['instanceId'] = nil
    end
    if !params[:public_ip].nil?
      instance['ipAddress'] = params[:public_ip]
      instance['dnsName'] = Fog::AWS::Mock.dns_name_for(params[:public_ip])
    end
    response.status = 200
    if !params[:instance_id].nil? && !params[:public_ip].nil?
      response.body = {
        'requestId' => Fog::AWS::Mock.request_id,
        'return'    => true
      }
    elsif !params[:allocation_id].nil?
      association_id = "eipassoc-#{Fog::Mock.random_hex(8)}"
      address['associationId'] = association_id
      response.body = {
        'requestId'     => Fog::AWS::Mock.request_id,
        'return'        => true,
        'associationId' => association_id,
      }
    end
    response
  elsif !instance
    raise Fog::AWS::Compute::NotFound.new("You must specify either an InstanceId or a NetworkInterfaceID")
  elsif !address
    raise Fog::AWS::Compute::Error.new("AuthFailure => The address '#{public_ip}' does not belong to you.")
  elsif params[:network_interface_id].nil? && params[:allocation_id].nil?
    raise Fog::AWS::Compute::NotFound.new("You must specify an AllocationId when specifying a NetworkInterfaceID")
  else (!instance.nil? && params[:network_interface_id].nil?) || (params[:instance_id].nil? && !params[:network_interface_id].nil?)
    raise Fog::AWS::Compute::Error.new("You must specify either an InstanceId or a NetworkInterfaceID")
  end
end

#associate_dhcp_options(dhcp_options_id, vpc_id) ⇒ Object



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/fog/aws/requests/compute/associate_dhcp_options.rb', line 32

def associate_dhcp_options(dhcp_options_id, vpc_id)
  response = Excon::Response.new
  if dhcp_options_id && vpc_id
    response.status = 200
    response.body = {
      'requestId' => Fog::AWS::Mock.request_id,
      'return' => true
    }
    response
  else
    if !dhcp_options_id
      message << 'The request must contain the parameter dhcp_options_id'
    elsif !vpc_id
      message << 'The request must contain the parameter vpc_id'
    end
    raise Fog::AWS::Compute::Error.new(message)
  end
end

#associate_route_table(routeTableId, subnetId) ⇒ Object



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/fog/aws/requests/compute/associate_route_table.rb', line 30

def associate_route_table(routeTableId, subnetId)
  routetable = self.data[:route_tables].find { |routetable| routetable["routeTableId"].eql? routeTableId }
  subnet = self.data[:subnets].find { |subnet| subnet["subnetId"].eql? subnetId }

  if !routetable.nil? && !subnet.nil?
    response = Excon::Response.new
    response.status = 200
    association = add_route_association(routeTableId, subnetId)
    routetable["associationSet"].push(association)
    response.body = {
        'requestId'     => Fog::AWS::Mock.request_id,
        'associationId' => association['routeTableAssociationId']
    }
    response
  elsif routetable.nil?
    raise Fog::AWS::Compute::NotFound.new("The routeTable ID '#{routeTableId}' does not exist")
  else
    raise Fog::AWS::Compute::NotFound.new("The subnet ID '#{subnetId}' does not exist")
  end
end


35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/fog/aws/requests/compute/attach_classic_link_vpc.rb', line 35

def attach_classic_link_vpc(instance_id, vpc_id, security_group_ids, dry_run=false)
  response = Excon::Response.new
  vpc = self.data[:vpcs].find{ |v| v['vpcId'] == vpc_id }
  instance = self.data[:instances][instance_id]
  if vpc && instance
    if instance['instanceState']['name'] != 'running' || instance['vpcId']
      raise Fog::AWS::Compute::Error.new("Client.InvalidInstanceID.NotLinkable => Instance #{instance_id} is unlinkable")
    end
    if instance['classicLinkVpcId']
      raise Fog::AWS::Compute::Error.new("Client.InvalidInstanceID.InstanceAlreadyLinked => Instance #{instance_id} is already linked")
    end

    response.status = 200
    response.body = {
      'requestId' => Fog::AWS::Mock.request_id,
      'return'    => true
    }
    unless dry_run
      instance['classicLinkSecurityGroups'] = security_group_ids
      instance['classicLinkVpcId'] = vpc_id
    end
    response
  elsif !instance
    raise Fog::AWS::Compute::NotFound.new("The instance ID '#{instance_id}' does not exist.")
  elsif !vpc
    raise Fog::AWS::Compute::NotFound.new("The VPC '#{vpc_id}' does not exist.")
  end

end

#attach_internet_gateway(internet_gateway_id, vpc_id) ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/fog/aws/requests/compute/attach_internet_gateway.rb', line 31

def attach_internet_gateway(internet_gateway_id, vpc_id)
  response = Excon::Response.new
  if internet_gateway_id && vpc_id
    response.status = 200
    response.body = {
      'requestId' => Fog::AWS::Mock.request_id,
      'return' => true
    }
    response
  else
    if !internet_gateway_id
      message << 'The request must contain the parameter internet_gateway_id'
    elsif !vpc_id
      message << 'The request must contain the parameter vpc_id'
    end
    raise Fog::AWS::Compute::Error.new(message)
  end
end

#attach_network_interface(nic_id, instance_id, device_index) ⇒ Object



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/fog/aws/requests/compute/attach_network_interface.rb', line 33

def attach_network_interface(nic_id, instance_id, device_index)
  response = Excon::Response.new
  if ! self.data[:instances].find{ |i,i_conf|
    i_conf['instanceId'] == instance_id
  }
    raise Fog::AWS::Compute::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::AWS::Compute::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 = {
      'requestId'    => Fog::AWS::Mock.request_id,
      'attachmentId' => attachment['attachmentId']
    }
  else
    raise Fog::AWS::Compute::NotFound.new("The network interface '#{nic_id}' does not exist")
  end

  response
end

#attach_volume(instance_id, volume_id, device) ⇒ Object



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/fog/aws/requests/compute/attach_volume.rb', line 38

def attach_volume(instance_id, volume_id, device)
  response = Excon::Response.new
  if instance_id && volume_id && device
    response.status = 200
    instance = self.data[:instances][instance_id]
    volume = self.data[:volumes][volume_id]
    if instance && volume
      unless volume['status'] == 'available'
        raise Fog::AWS::Compute::Error.new("Client.VolumeInUse => Volume #{volume_id} is unavailable")
      end

      data = {
        'attachTime'  => Time.now,
        'device'      => device,
        'instanceId'  => instance_id,
        'status'      => 'attaching',
        'volumeId'    => volume_id
      }
      volume['attachmentSet'] = [data]
      volume['status'] = 'attaching'
      response.status = 200
      response.body = {
        'requestId' => Fog::AWS::Mock.request_id
      }.merge!(data)
      response
    elsif !instance
      raise Fog::AWS::Compute::NotFound.new("The instance ID '#{instance_id}' does not exist.")
    elsif !volume
      raise Fog::AWS::Compute::NotFound.new("The volume '#{volume_id}' does not exist.")
    end
  else
    message = 'MissingParameter => '
    if !instance_id
      message << 'The request must contain the parameter instance_id'
    elsif !volume_id
      message << 'The request must contain the parameter volume_id'
    else
      message << 'The request must contain the parameter device'
    end
    raise Fog::AWS::Compute::Error.new(message)
  end
end

#authorize_security_group_egress(group_name, options = {}) ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/fog/aws/requests/compute/authorize_security_group_egress.rb', line 58

def authorize_security_group_egress(group_name, options = {})
  options = Fog::AWS.parse_security_group_options(group_name, options)

  group = if options.key?('GroupName')
            self.data[:security_groups].values.find { |v| v['groupName'] == options['GroupName'] }
          else
            self.data[:security_groups][options.fetch('GroupId')]
          end

  response = Excon::Response.new
  group ||
    raise(Fog::AWS::Compute::NotFound.new("The security group '#{group_name}' does not exist"))

  verify_permission_options(options, group['vpcId'] != nil)

  normalized_permissions = normalize_permissions(options)

  normalized_permissions.each do |permission|
    if matching_group_permission = find_matching_permission_egress(group, permission)
      if permission['groups'].any? {|pg| matching_group_permission['groups'].include?(pg) }
        raise Fog::AWS::Compute::Error, "InvalidPermission.Duplicate => The permission '123' has already been authorized in the specified group"
      end

      if permission['ipRanges'].any? {|pr| matching_group_permission['ipRanges'].include?(pr) }
        raise Fog::AWS::Compute::Error, "InvalidPermission.Duplicate => The permission '123' has already been authorized in the specified group"
      end
    end
  end

  normalized_permissions.each do |permission|
    if matching_group_permission = find_matching_permission_egress(group, permission)
      matching_group_permission['groups'] += permission['groups']
      matching_group_permission['ipRanges'] += permission['ipRanges']
    else
      group['ipPermissionsEgress'] << permission
    end
  end

  response.status = 200
  response.body = {
    'requestId' => Fog::AWS::Mock.request_id,
    'return'    => true
  }
  response
end

#authorize_security_group_ingress(group_name, options = {}) ⇒ Object



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/fog/aws/requests/compute/authorize_security_group_ingress.rb', line 81

def authorize_security_group_ingress(group_name, options = {})
  options = Fog::AWS.parse_security_group_options(group_name, options)

  group = if options.key?('GroupName')
            self.data[:security_groups].values.find { |v| v['groupName'] == options['GroupName'] }
          else
            self.data[:security_groups][options.fetch('GroupId')]
          end

  response = Excon::Response.new
  group ||
    raise(Fog::AWS::Compute::NotFound.new("The security group '#{group_name}' does not exist"))

  verify_permission_options(options, group['vpcId'] != nil)

  normalized_permissions = normalize_permissions(options)

  normalized_permissions.each do |permission|
    if matching_group_permission = find_matching_permission(group, permission)
      if permission['groups'].any? {|pg| matching_group_permission['groups'].include?(pg) }
        raise Fog::AWS::Compute::Error, "InvalidPermission.Duplicate => The permission '123' has already been authorized in the specified group"
      end

      if permission['ipRanges'].any? {|pr| matching_group_permission['ipRanges'].include?(pr) }
        raise Fog::AWS::Compute::Error, "InvalidPermission.Duplicate => The permission '123' has already been authorized in the specified group"
      end
    end
  end

  normalized_permissions.each do |permission|
    if matching_group_permission = find_matching_permission(group, permission)
      matching_group_permission['groups'] += permission['groups']
      matching_group_permission['ipRanges'] += permission['ipRanges']
    else
      group['ipPermissions'] << permission
    end
  end

  response.status = 200
  response.body = {
    'requestId' => Fog::AWS::Mock.request_id,
    'return'    => true
  }
  response
end

#cancel_spot_instance_requests(spot_instance_request_id) ⇒ Object



32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/fog/aws/requests/compute/cancel_spot_instance_requests.rb', line 32

def cancel_spot_instance_requests(spot_instance_request_id)
  response = Excon::Response.new
  spot_request = self.data[:spot_requests][spot_instance_request_id]

  unless spot_request
    raise Fog::AWS::Compute::NotFound.new("The spot instance request ID '#{spot_instance_request_id}' does not exist")
  end

  spot_request['fault']['code'] = 'request-cancelled'
  spot_request['state'] = 'cancelled'

  response.body = {'spotInstanceRequestSet' => [{'spotInstanceRequestId' => spot_instance_request_id, 'state' => 'cancelled'}], 'requestId' => Fog::AWS::Mock.request_id}
  response
end

#copy_image(source_image_id, source_region, name = nil, description = nil, client_token = nil) ⇒ Object

Usage

Fog::AWS.copy_image(“ami-1aad5273”, ‘us-east-1’)



43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/fog/aws/requests/compute/copy_image.rb', line 43

def copy_image(source_image_id, source_region, name = nil, description = nil, client_token = nil)
  response = Excon::Response.new
  response.status = 200
  image_id = Fog::AWS::Mock.image_id
  data = {
    'imageId'  => image_id,
  }
  self.data[:images][image_id] = data
  response.body = {
    'requestId' => Fog::AWS::Mock.request_id
  }.merge!(data)
  response
end

#copy_snapshot(source_snapshot_id, source_region, options = {}) ⇒ Object

Usage

Fog::AWS.copy_snapshot(“snap-1db0a957”, ‘us-east-1’)



51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/fog/aws/requests/compute/copy_snapshot.rb', line 51

def copy_snapshot(source_snapshot_id, source_region, options = {})
  response = Excon::Response.new
  response.status = 200
  snapshot_id = Fog::AWS::Mock.snapshot_id
  data = {
    'snapshotId'  => snapshot_id,
  }
  self.data[:snapshots][snapshot_id] = data
  response.body = {
    'requestId' => Fog::AWS::Mock.request_id
  }.merge!(data)
  response
end

#create_dhcp_options(dhcp_configurations = {}) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/fog/aws/requests/compute/create_dhcp_options.rb', line 42

def create_dhcp_options(dhcp_configurations = {})
  params = {}
  params.merge!(indexed_multidimensional_params(dhcp_configurations))
  Excon::Response.new.tap do |response|
    response.status = 200
    self.data[:dhcp_options].push({
      'dhcpOptionsId' => Fog::AWS::Mock.dhcp_options_id,
      'dhcpConfigurationSet'  => {},
      'tagSet'             => {}
    })
    response.body = {
      'requestId'    => Fog::AWS::Mock.request_id,
      'dhcpOptionsSet'      => self.data[:dhcp_options]
    }
  end
end

#create_image(instance_id, name, description, no_reboot = false, options = {}) ⇒ Object

Usage

Fog::AWS.create_image(“i-ac65ee8c”, “test”, “something”)



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/fog/aws/requests/compute/create_image.rb', line 53

def create_image(instance_id, name, description, no_reboot = false, options = {})
  params = {}
  block_device_mappings = options[:block_device_mappings] || []
  params.merge!Fog::AWS.indexed_param('BlockDeviceMapping.%d.DeviceName', block_device_mappings.map{|mapping| mapping['DeviceName']})
  params.merge!Fog::AWS.indexed_param('BlockDeviceMapping.%d.NoDevice', block_device_mappings.map{|mapping| mapping['NoDevice']})
  params.merge!Fog::AWS.indexed_param('BlockDeviceMapping.%d.VirtualName', block_device_mappings.map{|mapping| mapping['VirtualName']})
  params.merge!Fog::AWS.indexed_param('BlockDeviceMapping.%d.Ebs.SnapshotId', block_device_mappings.map{|mapping| mapping['Ebs.SnapshotId']})
  params.merge!Fog::AWS.indexed_param('BlockDeviceMapping.%d.Ebs.DeleteOnTermination', block_device_mappings.map{|mapping| mapping['Ebs.DeleteOnTermination']})
  params.merge!Fog::AWS.indexed_param('BlockDeviceMapping.%d.Ebs.VolumeType', block_device_mappings.map{|mapping| mapping['Ebs.VolumeType']})
  params.merge!Fog::AWS.indexed_param('BlockDeviceMapping.%d.Ebs.Encrypted', block_device_mappings.map{|mapping| mapping['Ebs.Encrypted']})
  params.merge!Fog::AWS.indexed_param('BlockDeviceMapping.%d.Ebs.Iops', block_device_mappings.map{|mapping| mapping['Ebs.Iops']})
  params.reject!{|k,v| v.nil?}

  reserved_ebs_root_device  = '/dev/sda1'
  block_devices = options.delete(:block_device_mappings) || []
  register_image_response = register_image(name, description, reserved_ebs_root_device, block_devices, options)

  response = Excon::Response.new
  if instance_id && !name.empty?
    response.status = 200
    response.body = {
      'requestId' => Fog::AWS::Mock.request_id,
      'imageId' => register_image_response.body['imageId']
    }
  else
    response.status = 400
    response.body = {
      'Code' => 'InvalidParameterValue'
    }
    if name.empty?
      response.body['Message'] = "Invalid value '' for name. Must be specified."
    end
  end
  response
end

#create_internet_gatewayObject



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/fog/aws/requests/compute/create_internet_gateway.rb', line 34

def create_internet_gateway()
  gateway_id = Fog::AWS::Mock.internet_gateway_id
self.data[:internet_gateways][gateway_id] = {
  'internetGatewayId' => gateway_id,
  'attachmentSet'     => {},
  'tagSet'            => {}
}
 Excon::Response.new(
    :status => 200,
    :body   => {
      'requestId' => Fog::AWS::Mock.request_id,
      'internetGatewaySet' => [self.data[:internet_gateways][gateway_id]]
    }
  )
end

#create_key_pair(key_name) ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/fog/aws/requests/compute/create_key_pair.rb', line 31

def create_key_pair(key_name)
  response = Excon::Response.new
  unless self.data[:key_pairs][key_name]
    response.status = 200
    data = {
      'keyFingerprint'  => Fog::AWS::Mock.key_fingerprint,
      'keyMaterial'     => Fog::AWS::Mock.key_material,
      'keyName'         => key_name
    }
    self.data[:key_pairs][key_name] = data
    response.body = {
      'requestId' => Fog::AWS::Mock.request_id
    }.merge!(data)
    response
  else
    raise Fog::AWS::Compute::Error.new("InvalidKeyPair.Duplicate => The keypair '#{key_name}' already exists.")
  end
end

#create_network_acl(vpcId, options = {}) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/fog/aws/requests/compute/create_network_acl.rb', line 51

def create_network_acl(vpcId, options = {})
  response = Excon::Response.new
  if vpcId
    id = Fog::AWS::Mock.network_acl_id

    unless self.data[:vpcs].find { |s| s['vpcId'] == vpcId }
      raise Fog::AWS::Compute::Error.new("Unknown VPC '#{vpcId}' specified")
    end

    data = {
      'networkAclId'   => id,
      'vpcId'          => vpcId,
      'default'        => false,
      'entrySet'       => [
        {
          'icmpTypeCode' => {},
          'portRange'    => {},
          'ruleNumber'   => 32767,
          'protocol'     => -1,
          'ruleAction'   => "deny",
          'egress'       => true,
          'cidrBlock'    => "0.0.0.0/0",
        },
        {
          'icmpTypeCode' => {},
          'portRange'    => {},
          'ruleNumber'   => 32767,
          'protocol'     => -1,
          'ruleAction'   => "deny",
          'egress'       => false,
          'cidrBlock'    => "0.0.0.0/0",
        },
      ],
      'associationSet' => [],
      'tagSet'         => {}
    }

    self.data[:network_acls][id] = data
    response.body = {
      'requestId'  => Fog::AWS::Mock.request_id,
      'networkAcl' => data
    }
  else
    response.status = 400
    response.body = {
      'Code'    => 'InvalidParameterValue',
      'Message' => "Invalid value '' for subnetId"
    }
  end
  response
end

#create_network_acl_entry(network_acl_id, rule_number, protocol, rule_action, cidr_block, egress, options = {}) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/fog/aws/requests/compute/create_network_acl_entry.rb', line 44

def create_network_acl_entry(network_acl_id, rule_number, protocol, rule_action, cidr_block, egress, options = {})
  response = Excon::Response.new
  if self.data[:network_acls][network_acl_id]

    if self.data[:network_acls][network_acl_id]['entrySet'].find { |r| r['ruleNumber'] == rule_number && r['egress'] == egress }
      raise Fog::AWS::Compute::Error.new("Already a rule with that number")
    end

    data = {
      'ruleNumber'   => rule_number,
      'protocol'     => protocol,
      'ruleAction'   => rule_action,
      'egress'       => egress,
      'cidrBlock'    => cidr_block,
      'icmpTypeCode' => {},
      'portRange'    => {}
    }
    data['icmpTypeCode']['code'] = options['Icmp.Code']      if options['Icmp.Code']
    data['icmpTypeCode']['type'] = options['Icmp.Type']      if options['Icmp.Type']
    data['portRange']['from']    = options['PortRange.From'] if options['PortRange.From']
    data['portRange']['to']      = options['PortRange.To']   if options['PortRange.To']
    self.data[:network_acls][network_acl_id]['entrySet'] << data

    response.status = 200
    response.body = {
      'requestId' => Fog::AWS::Mock.request_id,
      'return'    => true
    }
    response
  else
    raise Fog::AWS::Compute::NotFound.new("The network ACL '#{network_acl_id}' does not exist")
  end
end

#create_network_interface(subnetId, options = {}) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/fog/aws/requests/compute/create_network_interface.rb', line 63

def create_network_interface(subnetId, options = {})
  response = Excon::Response.new
  if subnetId
    subnet = self.data[:subnets].find{ |s| s['subnetId'] == subnetId }
    if subnet.nil?
      raise Fog::AWS::Compute::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|
          group_obj = self.data[:security_groups][group_id]
          if group_obj.nil?
            raise Fog::AWS::Compute::Error.new("Unknown security group '#{group_id}' specified")
          end
          groups[group_id] = group_obj['groupName']
        end
      end

      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::AWS::Compute::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 = {
      'Code'    => 'InvalidParameterValue',
      'Message' => "Invalid value '' for subnetId"
    }
  end
end

#create_route(route_table_id, destination_cidr_block, internet_gateway_id = nil, instance_id = nil, network_interface_id = nil) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/fog/aws/requests/compute/create_route.rb', line 42

def create_route(route_table_id, destination_cidr_block, internet_gateway_id=nil, instance_id=nil, network_interface_id=nil)
  instance_owner_id = nil
  route_table = self.data[:route_tables].find { |routetable| routetable["routeTableId"].eql? route_table_id }
  if !route_table.nil? && destination_cidr_block
    if !internet_gateway_id.nil? || !instance_id.nil? || !network_interface_id.nil?
      if !internet_gateway_id.nil? && self.internet_gateways.all('internet-gateway-id'=>internet_gateway_id).first.nil?
        raise Fog::AWS::Compute::NotFound.new("The gateway ID '#{internet_gateway_id}' does not exist")
      elsif !instance_id.nil? && self.servers.all('instance-id'=>instance_id).first.nil?
        raise Fog::AWS::Compute::NotFound.new("The instance ID '#{instance_id}' does not exist")
      elsif !network_interface_id.nil? && self.network_interfaces.all('networkInterfaceId'=>network_interface_id).first.nil?
        raise Fog::AWS::Compute::NotFound.new("The networkInterface ID '#{network_interface_id}' does not exist")
      elsif !route_table['routeSet'].find { |route| route['destinationCidrBlock'].eql? destination_cidr_block }.nil?
        raise Fog::AWS::Compute::Error, "RouteAlreadyExists => The route identified by #{destination_cidr_block} already exists."
      else
        response = Excon::Response.new
        route_table['routeSet'].push({
          "destinationCidrBlock" => destination_cidr_block,
          "gatewayId" => internet_gateway_id,
          "instanceId"=>instance_id,
          "instanceOwnerId"=>instance_owner_id,
          "networkInterfaceId"=>network_interface_id,
          "state" => "pending",
          "origin" => "CreateRoute"
        })
        response.status = 200
        response.body = {
          'requestId'=> Fog::AWS::Mock.request_id,
          'return' => true
        }
        response
      end
    else
      message = 'MissingParameter => '
      message << 'The request must contain either a gateway id, a network interface id, or an instance id'
      raise Fog::AWS::Compute::Error.new(message)
    end
  elsif route_table.nil?
    raise Fog::AWS::Compute::NotFound.new("The routeTable ID '#{route_table_id}' does not exist")
  elsif destination_cidr_block.empty?
    raise Fog::AWS::Compute::InvalidParameterValue.new("Value () for parameter destinationCidrBlock is invalid. This is not a valid CIDR block.")
  end
end

#create_route_table(vpc_id) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/fog/aws/requests/compute/create_route_table.rb', line 36

def create_route_table(vpc_id)
  response = Excon::Response.new
  vpc = self.data[:vpcs].find { |vpc| vpc["vpcId"].eql? vpc_id }
  unless vpc.nil?
    response.status = 200
    route_table = {
      'routeTableId' => Fog::AWS::Mock.route_table_id,
      'vpcId' => vpc["vpcId"],
      'routeSet' => [{
        "destinationCidrBlock" => vpc["cidrBlock"],
        "gatewayId" => "local",
        "instanceId"=>nil,
        "instanceOwnerId"=>nil,
        "networkInterfaceId"=>nil,
        "state" => "pending",
        "origin" => "CreateRouteTable"
      }],
      'associationSet' => [],
      'tagSet' => {}
    }
    self.data[:route_tables].push(route_table)
    response.body = {
      'requestId'=> Fog::AWS::Mock.request_id,
      'routeTable' => [route_table]
    }
    response
  else
    raise Fog::AWS::Compute::NotFound.new("The vpc ID '#{vpc_id}' does not exist")
  end
end

#create_security_group(name, description, vpc_id = nil) ⇒ Object



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/fog/aws/requests/compute/create_security_group.rb', line 34

def create_security_group(name, description, vpc_id=nil)
  response = Excon::Response.new

  vpc_id ||= Fog::AWS::Mock.default_vpc_for(region)
  group_id = Fog::AWS::Mock.security_group_id

  if self.data[:security_groups].find { |_,v| v['groupName'] == name }
    raise Fog::AWS::Compute::Error,
      "InvalidGroup.Duplicate => The security group '#{name}' already exists"
  end

  self.data[:security_groups][group_id] = {
    'groupDescription'    => description,
    'groupName'           => name,
    'groupId'             => group_id,
    'ipPermissionsEgress' => [],
    'ipPermissions'       => [],
    'ownerId'             => self.data[:owner_id],
    'vpcId'               => vpc_id
  }

  response.body = {
    'requestId' => Fog::AWS::Mock.request_id,
    'groupId'   => group_id,
    'return'    => true
  }
  response
end

#create_snapshot(volume_id, description = nil) ⇒ Object

Usage

Fog::AWS.create_snapshot(“vol-f7c23423”, “latest snapshot”)



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/fog/aws/requests/compute/create_snapshot.rb', line 41

def create_snapshot(volume_id, description = nil)
  response = Excon::Response.new
  if volume = self.data[:volumes][volume_id]
    response.status = 200
    snapshot_id = Fog::AWS::Mock.snapshot_id
    data = {
      'description' => description,
      'encrypted'   => false,
      'ownerId'     => self.data[:owner_id],
      'progress'    => nil,
      'snapshotId'  => snapshot_id,
      'startTime'   => Time.now,
      'status'      => 'pending',
      'volumeId'    => volume_id,
      'volumeSize'  => volume['size']
    }
    self.data[:snapshots][snapshot_id] = data
    response.body = {
      'requestId' => Fog::AWS::Mock.request_id
    }.merge!(data)
  else
    response.status = 400
    raise(Excon::Errors.status_error({:expects => 200}, response))
  end
  response
end

#create_subnet(vpcId, cidrBlock, options = {}) ⇒ Object



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/fog/aws/requests/compute/create_subnet.rb', line 45

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
      vpc = self.data[:vpcs].find{ |v| v['vpcId'] == vpcId }
      if vpc.nil?
        raise Fog::AWS::Compute::NotFound.new("The vpc ID '#{vpcId}' does not exist")
      end
      if ! ::IPAddress.parse(vpc['cidrBlock']).include?(::IPAddress.parse(cidrBlock))
        raise Fog::AWS::Compute::Error.new("Range => The CIDR '#{cidrBlock}' is invalid.")
      end
      self.data[:subnets].select{ |s| s['vpcId'] == vpcId }.each do |subnet|
        if ::IPAddress.parse(subnet['cidrBlock']).include?(::IPAddress.parse(cidrBlock))
          raise Fog::AWS::Compute::Error.new("Conflict => The CIDR '#{cidrBlock}' conflicts with another subnet")
        end
      end

      response.status = 200
      data = {
        'subnetId'                 => Fog::AWS::Mock.subnet_id,
        'state'                    => 'pending',
        'vpcId'                    => vpcId,
        'cidrBlock'                => cidrBlock,
        'availableIpAddressCount'  => "255",
        'availabilityZone'         => av_zone,
        'tagSet'                   => {},
        'mapPublicIpOnLaunch'      => true,
        'defaultForAz'             => true
      }

      # Add this subnet to the default network ACL
      accid = Fog::AWS::Mock.network_acl_association_id
      default_nacl = self.data[:network_acls].values.find { |nacl| nacl['vpcId'] == vpcId && nacl['default'] }
      default_nacl['associationSet'] << {
        'networkAclAssociationId' => accid,
        'networkAclId'            => default_nacl['networkAclId'],
        'subnetId'                => data['subnetId'],
      }

      self.data[:subnets].push(data)
      response.body = {
        'requestId'    => Fog::AWS::Mock.request_id,
        'subnet'       => data,
      }
    else
      response.status = 400
      response.body = {
        'Code' => 'InvalidParameterValue'
      }
      if cidrBlock.empty?
        response.body['Message'] = "Invalid value '' for cidrBlock. Must be specified."
      end
      if vpcId.empty?
        response.body['Message'] = "Invalid value '' for vpcId. Must be specified."
      end
    end
  end
end

#create_tags(resources, tags) ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/fog/aws/requests/compute/create_tags.rb', line 40

def create_tags(resources, tags)
  resources = [*resources]
  tagged = tagged_resources(resources)

  tags.each do |key, value|
    self.data[:tags][key] ||= {}
    self.data[:tags][key][value] ||= []
    self.data[:tags][key][value] |= tagged

    tagged.each do |resource|
      self.data[:tag_sets][resource['resourceId']][key] = value
    end
  end

  response = Excon::Response.new
  response.status = 200
  response.body = {
    'requestId' => Fog::AWS::Mock.request_id,
    'return'    => true
  }
  response
end

#create_volume(availability_zone, size, options = {}) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/fog/aws/requests/compute/create_volume.rb', line 48

def create_volume(availability_zone, size, options = {})
  unless options.is_a?(Hash)
    Fog::Logger.deprecation("create_volume with a bare snapshot_id is deprecated, use create_volume(availability_zone, size, 'SnapshotId' => snapshot_id) instead [light_black](#{caller.first})[/]")
    options = { 'SnapshotId' => options }
  end

  response = Excon::Response.new
  if availability_zone && (size || options['SnapshotId'])
    snapshot = self.data[:snapshots][options['SnapshotId']]
    if options['SnapshotId'] && !snapshot
      raise Fog::AWS::Compute::NotFound.new("The snapshot '#{options['SnapshotId']}' does not exist.")
    end

    if snapshot && size && size < snapshot['volumeSize']
      raise Fog::AWS::Compute::NotFound.new("The snapshot '#{options['SnapshotId']}' has size #{snapshot['volumeSize']} which is greater than #{size}.")
    elsif snapshot && !size
      size = snapshot['volumeSize']
    end

    if options['VolumeType'] == 'io1'
      iops = options['Iops']
      if !iops
        raise Fog::AWS::Compute::Error.new("InvalidParameterCombination => The parameter iops must be specified for io1 volumes.")
      end

      if size < 10
        raise Fog::AWS::Compute::Error.new("InvalidParameterValue => Volume of #{size}GiB is too small; minimum is 10GiB.")
      end

      if (iops_to_size_ratio = iops.to_f / size.to_f) > 30.0
        raise Fog::AWS::Compute::Error.new("InvalidParameterValue => Iops to volume size ratio of #{"%.1f" % iops_to_size_ratio} is too high; maximum is 30.0")
      end

      if iops < 100
        raise Fog::AWS::Compute::Error.new("VolumeIOPSLimit => Volume iops of #{iops} is too low; minimum is 100.")
      end

      if iops > 4000
        raise Fog::AWS::Compute::Error.new("VolumeIOPSLimit => Volume iops of #{iops} is too high; maximum is 4000.")
      end
    end

    if options['KmsKeyId'] && !options['Encrypted']
      raise Fog::AWS::Compute::Error.new("InvalidParameterDependency => The parameter KmsKeyId requires the parameter Encrypted to be set.")
    end

    response.status = 200
    volume_id = Fog::AWS::Mock.volume_id
    data = {
      'availabilityZone' => availability_zone,
      'attachmentSet'    => [],
      'createTime'       => Time.now,
      'iops'             => options['Iops'],
      'encrypted'        => options['Encrypted'] || false,
      'size'             => size,
      'snapshotId'       => options['SnapshotId'],
      'kmsKeyId'         => options['KmsKeyId'] || nil, # @todo validate
      'status'           => 'creating',
      'volumeId'         => volume_id,
      'volumeType'       => options['VolumeType'] || 'standard'
    }
    self.data[:volumes][volume_id] = data
    response.body = {
      'requestId' => Fog::AWS::Mock.request_id
    }.merge!(data.reject {|key,value| !['availabilityZone','createTime','encrypted','size','snapshotId','status','volumeId','volumeType'].include?(key) })
  else
    response.status = 400
    response.body = {
      'Code' => 'MissingParameter'
    }
    unless availability_zone
      response.body['Message'] = 'The request must contain the parameter availability_zone'
    else
      response.body['Message'] = 'The request must contain the parameter size'
    end
  end
  response
end

#create_vpc(cidrBlock, options = {}) ⇒ Object



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/fog/aws/requests/compute/create_vpc.rb', line 39

def create_vpc(cidrBlock, options = {})
  Excon::Response.new.tap do |response|
    if cidrBlock
      response.status = 200
      vpc_id = Fog::AWS::Mock.vpc_id
      vpc = {
        'vpcId'                       => vpc_id,
        'state'                       => 'pending',
        'cidrBlock'                   => cidrBlock,
        'dhcpOptionsId'               => Fog::AWS::Mock.request_id,
        'tagSet'                      => {},
        'enableDnsSupport'            => true,
        'enableDnsHostnames'          => false,
        'mapPublicIpOnLaunch'         => false,
        'classicLinkEnabled'          => false,
        'classicLinkDnsSupport'       => false,
        'cidrBlockAssociationSet'     => [{ 'cidrBlock' => cidrBlock, 'state' => 'associated', 'associationId' => "vpc-cidr-assoc-#{vpc_id}" }],
        'ipv6CidrBlockAssociationSet' => [],
        'instanceTenancy'             => options['InstanceTenancy'] || 'default'
      }
      self.data[:vpcs].push(vpc)

      #Creates a default route for the subnet
      default_route = self.route_tables.new(:vpc_id => vpc_id)
      default_route.save

      # You are not able to push a main route in the normal AWS, so we are re-implementing some of the
      # associate_route_table here in order to accomplish this.
      route_table = self.data[:route_tables].find { |routetable| routetable["routeTableId"].eql? default_route.id }

      # This pushes a main route to the associationSet
      # add_route_association(routeTableId, subnetId, main=false) is declared in assocate_route_table.rb
      assoc = add_route_association(default_route.id, nil, true)
      route_table["associationSet"].push(assoc)

      # Create a default network ACL
      default_nacl = self.network_acls.new(:vpc_id => vpc_id)
      default_nacl.save
      # Manually override since Amazon doesn't let you create a default one
      self.data[:network_acls][default_nacl.network_acl_id]['default'] = true


      # create default security groups
      default_elb_group_name = "default_elb_#{Fog::Mock.random_hex(6)}"
      default_elb_group_id = Fog::AWS::Mock.security_group_id

      Fog::AWS::Compute::Mock.data[region][@aws_access_key_id][:security_groups][default_elb_group_id] = {
        'groupDescription'    => 'default_elb security group',
        'groupName'           => default_elb_group_name,
        'groupId'             => default_elb_group_id,
        'ipPermissions'       => [],
        'ownerId'             => self.data[:owner_id],
        'vpcId'               => vpc_id
      }

      default_group_name = 'default'
      default_group_id = Fog::AWS::Mock.security_group_id

      Fog::AWS::Compute::Mock.data[region][@aws_access_key_id][:security_groups][default_group_id] = {
        'groupDescription'    => default_group_name,
        'groupName'           => default_group_name,
        'groupId'             => default_group_id,
        'ipPermissions'       => [],
        'ownerId'             => self.data[:owner_id],
        'vpcId'               => vpc_id
      }

      response.body = {
        'requestId' => Fog::AWS::Mock.request_id,
        'vpcSet'    => [vpc]
      }
    else
      response.status = 400
      response.body = {
        'Code' => 'InvalidParameterValue'
      }
      if cidrBlock.empty?
        response.body['Message'] = "Invalid value '' for cidrBlock. Must be specified."
      end
    end
  end
end

#dataObject



342
343
344
# File 'lib/fog/aws/compute.rb', line 342

def data
  self.region_data[@aws_access_key_id]
end

#default_vpcObject



382
383
384
385
# File 'lib/fog/aws/compute.rb', line 382

def default_vpc
  vpc_id = .body["accountAttributeSet"].find{ |h| h["attributeName"] == "default-vpc" }["values"].first
  vpc_id == VPC_BLANK_VALUE ? nil : vpc_id
end

#default_vpc=(value) ⇒ Object



387
388
389
# File 'lib/fog/aws/compute.rb', line 387

def default_vpc=(value)
  self.data[:account_attributes].find { |h| h["attributeName"] == "default-vpc" }["values"] = [value]
end

#delete_dhcp_options(dhcp_options_id) ⇒ Object



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/fog/aws/requests/compute/delete_dhcp_options.rb', line 30

def delete_dhcp_options(dhcp_options_id)
  Excon::Response.new.tap do |response|
    if dhcp_options_id
      response.status = 200
      self.data[:dhcp_options].reject! { |v| v['dhcpOptionsId'] == dhcp_options_id }

      response.body = {
        'requestId' => Fog::AWS::Mock.request_id,
        'return' => true
      }
    else
      message = 'MissingParameter => '
      message << 'The request must contain the parameter dhcp_options_id'
      raise Fog::AWS::Compute::Error.new(message)
    end
  end
end

#delete_internet_gateway(internet_gateway_id) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/fog/aws/requests/compute/delete_internet_gateway.rb', line 28

def delete_internet_gateway(internet_gateway_id)
  Excon::Response.new.tap do |response|
    if internet_gateway_id
      response.status = 200
      self.data[:internet_gateways].delete(internet_gateway_id)

      response.body = {
        'requestId' => Fog::AWS::Mock.request_id,
        'return' => true
      }
    else
      message = 'MissingParameter => '
      message << 'The request must contain the parameter internet_gateway_id'
      raise Fog::AWS::Compute::Error.new(message)
    end
  end
end

#delete_key_pair(key_name) ⇒ Object



30
31
32
33
34
35
36
37
38
39
# File 'lib/fog/aws/requests/compute/delete_key_pair.rb', line 30

def delete_key_pair(key_name)
  response = Excon::Response.new
  self.data[:key_pairs].delete(key_name)
  response.status = 200
  response.body = {
    'requestId' => Fog::AWS::Mock.request_id,
    'return'    => true
  }
  response
end

#delete_network_acl(network_acl_id) ⇒ Object



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/fog/aws/requests/compute/delete_network_acl.rb', line 29

def delete_network_acl(network_acl_id)
  response = Excon::Response.new
  if self.data[:network_acls][network_acl_id]

    if self.data[:network_acls][network_acl_id]['associationSet'].any?
      raise Fog::AWS::Compute::Error.new("ACL is in use")
    end

    self.data[:network_acls].delete(network_acl_id)

    response.status = 200
    response.body = {
      'requestId' => Fog::AWS::Mock.request_id,
      'return'    => true
    }
    response
  else
    raise Fog::AWS::Compute::NotFound.new("The network ACL '#{network_acl_id}' does not exist")
  end
end

#delete_network_acl_entry(network_acl_id, rule_number, egress) ⇒ Object



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/fog/aws/requests/compute/delete_network_acl_entry.rb', line 33

def delete_network_acl_entry(network_acl_id, rule_number, egress)
  response = Excon::Response.new
  if self.data[:network_acls][network_acl_id]
    if self.data[:network_acls][network_acl_id]['entrySet'].find { |r| r['ruleNumber'] == rule_number && r['egress'] == egress }
      self.data[:network_acls][network_acl_id]['entrySet'].delete_if { |r| r['ruleNumber'] == rule_number && r['egress'] == egress }
    else
      raise Fog::AWS::Compute::Error.new("No rule with that number and egress value")
    end

    response.status = 200
    response.body = {
      'requestId' => Fog::AWS::Mock.request_id,
      'return'    => true
    }
    response
  else
    raise Fog::AWS::Compute::NotFound.new("The network ACL '#{network_acl_id}' does not exist")
  end
end

#delete_network_interface(network_interface_id) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/fog/aws/requests/compute/delete_network_interface.rb', line 28

def delete_network_interface(network_interface_id)
  response = Excon::Response.new
  if self.data[:network_interfaces][network_interface_id]

    if self.data[:network_interfaces][network_interface_id]['attachment']['attachmentId']
      raise Fog::AWS::Compute::Error.new("Interface is in use")
    end

    self.data[:network_interfaces].delete(network_interface_id)

    response.status = 200
    response.body = {
      'requestId' => Fog::AWS::Mock.request_id,
      'return'    => true
    }
    response
  else
    raise Fog::AWS::Compute::NotFound.new("The network interface '#{network_interface_id}' does not exist")
  end
end

#delete_route(route_table_id, destination_cidr_block) ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/fog/aws/requests/compute/delete_route.rb', line 31

def delete_route(route_table_id, destination_cidr_block)
  route_table = self.data[:route_tables].find { |routetable| routetable["routeTableId"].eql? route_table_id }
  unless route_table.nil?
    route = route_table['routeSet'].find { |route| route["destinationCidrBlock"].eql? destination_cidr_block }
    if !route.nil? && route['gatewayId'] != "local"
      route_table['routeSet'].delete(route)
      response = Excon::Response.new
      response.status = 200
      response.body = {
        'requestId'=> Fog::AWS::Mock.request_id,
        'return' => true
      }
      response
    elsif route['gatewayId'] == "local"
      # Cannot delete the default route
      raise Fog::AWS::Compute::Error, "InvalidParameterValue => cannot remove local route #{destination_cidr_block} in route table #{route_table_id}"
    else
      raise Fog::AWS::Compute::NotFound.new("no route with destination-cidr-block #{destination_cidr_block} in route table #{route_table_id}")
    end
  else
    raise Fog::AWS::Compute::NotFound.new("no route with destination-cidr-block #{destination_cidr_block} in route table #{route_table_id}")
  end
end

#delete_route_table(route_table_id) ⇒ Object



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/fog/aws/requests/compute/delete_route_table.rb', line 29

def delete_route_table(route_table_id)
  route_table = self.data[:route_tables].find { |routetable| routetable["routeTableId"].eql? route_table_id }
  if !route_table.nil? && route_table['associationSet'].empty?
    self.data[:route_tables].delete(route_table)
      response = Excon::Response.new
      response.status = 200
      response.body = {
        'requestId'=> Fog::AWS::Mock.request_id,
        'return' => true
      }
      response
  elsif route_table.nil?
    raise Fog::AWS::Compute::NotFound.new("The routeTable ID '#{route_table_id}' does not exist")
  elsif !route_table['associationSet'].empty?
    raise Fog::AWS::Compute::Error, "DependencyViolation => The routeTable '#{route_table_id}' has dependencies and cannot be deleted."
  end
end

#delete_security_group(name, id = nil) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/fog/aws/requests/compute/delete_security_group.rb', line 41

def delete_security_group(name, id = nil)
  if name == 'default'
    raise Fog::AWS::Compute::Error.new("InvalidGroup.Reserved => The security group 'default' is reserved")
  end

  if name && id
    raise Fog::AWS::Compute::Error.new("May not specify both group_name and group_id")
  end

  if name
    id, _ = self.data[:security_groups].find { |_,v| v['groupName'] == name }
  end

  unless self.data[:security_groups][id]
    raise Fog::AWS::Compute::NotFound.new("The security group '#{id}' does not exist")
  end

  response = Excon::Response.new

  used_by_groups = []

  # ec2 authorizations
  self.region_data.each do |_, key_data|
    key_data[:security_groups].each do |group_id, group|
      next if group == self.data[:security_groups][group_id]

      group['ipPermissions'].each do |group_ip_permission|
        group_ip_permission['groups'].each do |group_group_permission|
          if group_group_permission['groupId'] == group_id &&
              group_group_permission['userId'] == self.data[:owner_id]
            used_by_groups << "#{key_data[:owner_id]}:#{group['groupName']}"
          end
        end
      end
    end
  end

  # rds authorizations
  Fog::AWS::RDS::Mock.data[self.region].each do |_, data|
    (data[:security_groups] || []).each do |group_name, group|
      (group["EC2SecurityGroups"] || []).each do |ec2_group|
        if ec2_group["EC2SecurityGroupName"] == name
          used_by_groups << "#{group["OwnerId"]}:#{group_name}"
        end
      end
    end
  end

  active_instances = self.data[:instances].values.select do |instance|
    if instance['groupSet'].include?(name) && instance['instanceState'] != "terminated"
      instance
    end
  end

  unless used_by_groups.empty?
    raise Fog::AWS::Compute::Error.new("InvalidGroup.InUse => Group #{self.data[:owner_id]}:#{name} is used by groups: #{used_by_groups.uniq.join(" ")}")
  end

  if active_instances.any?
    raise Fog::AWS::Compute::Error.new("InUse => There are active instances using security group '#{name}'")
  end

  self.data[:security_groups].delete(id)
  response.status = 200
  response.body = {
    'requestId' => Fog::AWS::Mock.request_id,
    'return'    => true
  }
  response
end

#delete_snapshot(snapshot_id) ⇒ Object



30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/fog/aws/requests/compute/delete_snapshot.rb', line 30

def delete_snapshot(snapshot_id)
  response = Excon::Response.new
  if snapshot = self.data[:snapshots].delete(snapshot_id)
    response.status = true
    response.body = {
      'requestId' => Fog::AWS::Mock.request_id,
      'return'    => true
    }
    response
  else
    raise Fog::AWS::Compute::NotFound.new("The snapshot '#{snapshot_id}' does not exist.")
  end
end

#delete_subnet(subnet_id) ⇒ Object



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/fog/aws/requests/compute/delete_subnet.rb', line 29

def delete_subnet(subnet_id)
  Excon::Response.new.tap do |response|
    if subnet_id
      self.data[:subnets].reject! { |v| v['subnetId'] == subnet_id }
      response.status = 200

      response.body = {
        'requestId' => Fog::AWS::Mock.request_id,
        'return' => true
      }
    else
      message = 'MissingParameter => '
      message << 'The request must contain the parameter subnet_id'
      raise Fog::AWS::Compute::Error.new(message)
    end
  end
end

#delete_tags(resources, tags) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/fog/aws/requests/compute/delete_tags.rb', line 42

def delete_tags(resources, tags)
  tagged = tagged_resources(resources)

  tags.each do |key, value|
    self.data[:tags][key][value] = self.data[:tags][key][value] - tagged
  end

  tagged.each do |resource|
    tags.each do |key, value|
      tagset = self.data[:tag_sets][resource['resourceId']]
      tagset.delete(key) if tagset.key?(key) && (value.nil? || tagset[key] == value)
    end
  end

  response = Excon::Response.new
  response.status = true
  response.body = {
    'requestId' => Fog::AWS::Mock.request_id,
    'return'    => true
  }
  response
end

#delete_volume(volume_id) ⇒ Object



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/fog/aws/requests/compute/delete_volume.rb', line 30

def delete_volume(volume_id)
  response = Excon::Response.new
  if volume = self.data[:volumes][volume_id]
    if volume["attachmentSet"].any?
      attach = volume["attachmentSet"].first
      raise Fog::AWS::Compute::Error.new("Client.VolumeInUse => Volume #{volume_id} is currently attached to #{attach["instanceId"]}")
    end
    self.data[:deleted_at][volume_id] = Time.now
    volume['status'] = 'deleting'
    response.status = 200
    response.body = {
      'requestId' => Fog::AWS::Mock.request_id,
      'return'    => true
    }
    response
  else
    raise Fog::AWS::Compute::NotFound.new("The volume '#{volume_id}' does not exist.")
  end
end

#delete_vpc(vpc_id) ⇒ Object



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/fog/aws/requests/compute/delete_vpc.rb', line 32

def delete_vpc(vpc_id)
  Excon::Response.new.tap do |response|
    if vpc_id
      response.status = 200
      self.data[:vpcs].reject! { |v| v['vpcId'] == vpc_id }

      # Delete the default network ACL
      network_acl_id = self.network_acls.all('vpc-id' => vpc_id, 'default' => true).first.network_acl_id
      self.data[:network_acls].delete(network_acl_id)

      response.body = {
        'requestId' => Fog::AWS::Mock.request_id,
        'return' => true
      }
    else
      message = 'MissingParameter => '
      message << 'The request must contain the parameter vpc_id'
      raise Fog::AWS::Compute::Error.new(message)
    end
  end
end

#deregister_image(image_id) ⇒ Object



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/fog/aws/requests/compute/deregister_image.rb', line 29

def deregister_image(image_id)
  response = Excon::Response.new
  if image_id
    response.status = 200
    response.body = {
      'requestId' => Fog::AWS::Mock.request_id,
      'return' => "true"
    }
    response
  else
    message = 'MissingParameter => '
    if !instance_id
      message << 'The request must contain the parameter image_id'
    end
    raise Fog::AWS::Compute::Error.new(message)
  end
end

#describe_account_attributes(filters = {}) ⇒ Object



34
35
36
37
38
39
40
41
42
43
44
# File 'lib/fog/aws/requests/compute/describe_account_attributes.rb', line 34

def (filters = {})
   = self.data[:account_attributes]

  Excon::Response.new(
    :status => 200,
    :body => {
      'requestId'           => Fog::AWS::Mock.request_id,
      'accountAttributeSet' => 
    }
  )
end

#describe_addresses(filters = {}) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/fog/aws/requests/compute/describe_addresses.rb', line 36

def describe_addresses(filters = {})
  unless filters.is_a?(Hash)
    Fog::Logger.deprecation("describe_addresses with #{filters.class} param is deprecated, use describe_addresses('public-ip' => []) instead [light_black](#{caller.first})[/]")
    filters = {'public-ip' => [*filters]}
  end

  response = Excon::Response.new

  addresses_set = self.data[:addresses].values

  aliases = {'public-ip' => 'publicIp', 'instance-id' => 'instanceId', 'allocation-id' => 'allocationId'}
  for filter_key, filter_value in filters
    aliased_key = aliases[filter_key]
    addresses_set = addresses_set.reject{|address| ![*filter_value].include?(address[aliased_key])}
  end

  response.status = 200
  response.body = {
    'requestId'     => Fog::AWS::Mock.request_id,
    'addressesSet'  => addresses_set
  }
  response
end

#describe_availability_zones(filters = {}) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/fog/aws/requests/compute/describe_availability_zones.rb', line 37

def describe_availability_zones(filters = {})
  unless filters.is_a?(Hash)
    Fog::Logger.deprecation("describe_availability_zones with #{filters.class} param is deprecated, use describe_availability_zones('zone-name' => []) instead [light_black](#{caller.first})[/]")
    filters = {'zone-name' => [*filters]}
  end

  response = Excon::Response.new

  all_zones = [
    {"messageSet" => [], "regionName" => "us-east-1", "zoneName" => "us-east-1a", "zoneState" => "available"},
    {"messageSet" => [], "regionName" => "us-east-1", "zoneName" => "us-east-1b", "zoneState" => "available"},
    {"messageSet" => [], "regionName" => "us-east-1", "zoneName" => "us-east-1c", "zoneState" => "available"},
    {"messageSet" => [], "regionName" => "us-east-1", "zoneName" => "us-east-1d", "zoneState" => "available"},
    {"messageSet" => [], "regionName" => "us-east-1", "zoneName" => "us-east-1e", "zoneState" => "available"},

    {"messageSet" => [], "regionName" => "us-east-2", "zoneName" => "us-east-2a", "zoneState" => "available"},
    {"messageSet" => [], "regionName" => "us-east-2", "zoneName" => "us-east-2b", "zoneState" => "available"},
    {"messageSet" => [], "regionName" => "us-east-2", "zoneName" => "us-east-2c", "zoneState" => "available"},

    {"messageSet" => [], "regionName" => "us-west-1", "zoneName" => "us-west-1a", "zoneState" => "available"},
    {"messageSet" => [], "regionName" => "us-west-1", "zoneName" => "us-west-1b", "zoneState" => "available"},
    {"messageSet" => [], "regionName" => "us-west-1", "zoneName" => "us-west-1c", "zoneState" => "available"},

    {"messageSet" => [], "regionName" => "us-west-2", "zoneName" => "us-west-2a", "zoneState" => "available"},
    {"messageSet" => [], "regionName" => "us-west-2", "zoneName" => "us-west-2b", "zoneState" => "available"},

    {"messageSet" => [], "regionName" => "sa-east-1", "zoneName" => "sa-east-1a", "zoneState" => "available"},
    {"messageSet" => [], "regionName" => "sa-east-1", "zoneName" => "sa-east-1b", "zoneState" => "available"},

    {"messageSet" => [], "regionName" => "eu-west-1", "zoneName" => "eu-west-1a", "zoneState" => "available"},
    {"messageSet" => [], "regionName" => "eu-west-1", "zoneName" => "eu-west-1b", "zoneState" => "available"},
    {"messageSet" => [], "regionName" => "eu-west-1", "zoneName" => "eu-west-1c", "zoneState" => "available"},

    {"messageSet" => [], "regionName" => "eu-west-2", "zoneName" => "eu-west-2a", "zoneState" => "available"},
    {"messageSet" => [], "regionName" => "eu-west-2", "zoneName" => "eu-west-2b", "zoneState" => "available"},

    {"messageSet" => [], "regionName" => "eu-west-3", "zoneName" => "eu-west-3a", "zoneState" => "available"},
    {"messageSet" => [], "regionName" => "eu-west-3", "zoneName" => "eu-west-3b", "zoneState" => "available"},

    {"messageSet" => [], "regionName" => "eu-central-1", "zoneName" => "eu-central-1a", "zoneState" => "available"},
    {"messageSet" => [], "regionName" => "eu-central-1", "zoneName" => "eu-central-1b", "zoneState" => "available"},

    {"messageSet" => [], "regionName" => "ca-central-1", "zoneName" => "ca-central-1a", "zoneState" => "available"},
    {"messageSet" => [], "regionName" => "ca-central-1", "zoneName" => "ca-central-1b", "zoneState" => "available"},

    {"messageSet" => [], "regionName" => "ap-northeast-1", "zoneName" => "ap-northeast-1a", "zoneState" => "available"},
    {"messageSet" => [], "regionName" => "ap-northeast-1", "zoneName" => "ap-northeast-1b", "zoneState" => "available"},

    {"messageSet" => [], "regionName" => "ap-northeast-2", "zoneName" => "ap-northeast-2a", "zoneState" => "available"},
    {"messageSet" => [], "regionName" => "ap-northeast-2", "zoneName" => "ap-northeast-2b", "zoneState" => "available"},

    {"messageSet" => [], "regionName" => "ap-southeast-1", "zoneName" => "ap-southeast-1a", "zoneState" => "available"},
    {"messageSet" => [], "regionName" => "ap-southeast-1", "zoneName" => "ap-southeast-1b", "zoneState" => "available"},

    {"messageSet" => [], "regionName" => "ap-southeast-2", "zoneName" => "ap-southeast-2a", "zoneState" => "available"},
    {"messageSet" => [], "regionName" => "ap-southeast-2", "zoneName" => "ap-southeast-2b", "zoneState" => "available"},

    {"messageSet" => [], "regionName" => "ap-south-1", "zoneName" => "ap-south-1a", "zoneState" => "available"},
    {"messageSet" => [], "regionName" => "ap-south-1", "zoneName" => "ap-south-1b", "zoneState" => "available"},
  ]

  availability_zone_info = all_zones.select { |zoneinfo| zoneinfo["regionName"] == @region }

  aliases = {'region-name' => 'regionName', 'zone-name' => 'zoneName', 'state' => 'zoneState'}
  for filter_key, filter_value in filters
    aliased_key = aliases[filter_key]
    availability_zone_info = availability_zone_info.reject{|availability_zone| ![*filter_value].include?(availability_zone[aliased_key])}
  end

  response.status = 200
  response.body = {
    'availabilityZoneInfo'  => availability_zone_info,
    'requestId'             => Fog::AWS::Mock.request_id
  }
  response
end


41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/fog/aws/requests/compute/describe_classic_link_instances.rb', line 41

def describe_classic_link_instances(options={})
  response = Excon::Response.new
  instances = self.data[:instances].values.select {|instance| instance['classicLinkVpcId']}
  if options[:filters]
    instances = apply_tag_filters(instances, options[:filters], 'instanceId')
    instances = instances.select {|instance| instance['classicLinkVpcId'] == options[:filters]['vpc-id']} if options[:filters]['vpc-id']
    instances = instances.select {|instance| instance['instanceId'] == options[:filters]['instance-id']} if options[:filters]['instance-id']
    instances = instances.select {|instance| instance['classicLinkSecurityGroups'].include?(options[:filters]['group-id'])} if options[:filters]['group-id']
  end
  instances = instances.select {|instance| options[:instance_ids].include?(instance['instanceId'])} if options[:instance_ids]



  response.status = 200
  instance_data = instances.collect do |instance| 
    groups = self.data[:security_groups].values.select {|data| instance['classicLinkSecurityGroups'].include?(data['groupId'])}
    {
      'instanceId' => instance['instanceId'],
      'vpcId' => instance['classicLinkVpcId'],
      'groups' => groups.collect {|group| {'groupId' => group['groupId'], 'groupName' => group['groupName']}},
      'tagSet' => self.data[:tag_sets][instance['instanceId']] || {}
    }
  end
  response.body = {
    'requestId' => Fog::AWS::Mock.request_id,
    'instancesSet' => instance_data
  }
  response
end

#describe_dhcp_options(filters = {}) ⇒ Object



42
43
44
45
46
47
48
49
50
# File 'lib/fog/aws/requests/compute/describe_dhcp_options.rb', line 42

def describe_dhcp_options(filters = {})
  Excon::Response.new.tap do |response|
    response.status = 200
    response.body = {
      'requestId' => Fog::AWS::Mock.request_id,
      'dhcpOptionsSet'    => self.data[:dhcp_options]
    }
  end
end

#describe_image_attribute(image_id, attribute) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/fog/aws/requests/compute/describe_image_attribute.rb', line 42

def describe_image_attribute(image_id, attribute)
  response = Excon::Response.new
  if image = self.data[:images].values.find{ |i| i['imageId'] == image_id }
    response.status = 200
    response.body = {
      'requestId' => Fog::AWS::Mock.request_id,
      'imageId'     => image_id
    }
    case attribute
    when 'kernel'
      response.body[attribute] = image["kernelId"]
    when 'ramdisk'
      response.body[attribute] = image["ramdiskId"]
    when 'sriovNetSupport'
      response.body[attribute] = 'simple'
    when 'launchPermission'
      if image_launch_permissions = self.data[:image_launch_permissions][image_id]
        response.body[attribute] = image_launch_permissions[:users]
      else
        response.body[attribute] = []
      end
    else
      response.body[attribute] = image[attribute]
    end
  response
  else
    raise Fog::AWS::Compute::NotFound.new("The Image '#{image_id}' does not exist")
  end
end

#describe_images(filters = {}) ⇒ Object



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/fog/aws/requests/compute/describe_images.rb', line 60

def describe_images(filters = {})
  unless filters.is_a?(Hash)
    Fog::Logger.deprecation("describe_images with #{filters.class} param is deprecated, use describe_images('image-id' => []) instead [light_black](#{caller.first})[/]")
    filters = {'image-id' => [*filters]}
  end

  if filters.keys.any? {|key| key =~ /^block-device/}
    Fog::Logger.warning("describe_images block-device-mapping filters are not yet mocked [light_black](#{caller.first})[/]")
    Fog::Mock.not_implemented
  end

  if owner = filters.delete('Owner')
    if owner == 'self'
      filters['owner-id'] = self.data[:owner_id]
    else
      filters['owner-alias'] = owner
    end
  end

  response = Excon::Response.new

  aliases = {
    'architecture'        => 'architecture',
    'description'         => 'description',
    'hypervisor'          => 'hypervisor',
    'image-id'            => 'imageId',
    'image-type'          => 'imageType',
    'is-public'           => 'isPublic',
    'kernel-id'           => 'kernelId',
    'manifest-location'   => 'manifestLocation',
    'name'                => 'name',
    'owner-alias'         => 'imageOwnerAlias',
    'owner-id'            => 'imageOwnerId',
    'ramdisk-id'          => 'ramdiskId',
    'root-device-name'    => 'rootDeviceName',
    'root-device-type'    => 'rootDeviceType',
    'state'               => 'imageState',
    'virtualization-type' => 'virtualizationType'
  }

  image_set = visible_images.values
  image_set = apply_tag_filters(image_set, filters, 'imageId')

  for filter_key, filter_value in filters
    aliased_key = aliases[filter_key]
    image_set = image_set.reject{|image| ![*filter_value].include?(image[aliased_key])}
  end

  image_set = image_set.map do |image|
    case image['imageState']
    when 'pending'
      if Time.now - image['registered'] >= Fog::Mock.delay
        image['imageState'] = 'available'
      end
    end
    image.reject { |key, value| ['registered'].include?(key) }.merge('tagSet' => self.data[:tag_sets][image['imageId']])
  end

  response.status = 200
  response.body = {
    'requestId' => Fog::AWS::Mock.request_id,
    'imagesSet' => image_set
  }
  response
end

#describe_instance_attribute(instance_id, attribute) ⇒ Object



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/fog/aws/requests/compute/describe_instance_attribute.rb', line 55

def describe_instance_attribute(instance_id, attribute)
  response = Excon::Response.new
  if instance = self.data[:instances].values.find{ |i| i['instanceId'] == instance_id }
    response.status = 200
    response.body = {
      'requestId' => Fog::AWS::Mock.request_id,
      'instanceId'     => instance_id
    }
    case attribute
    when 'kernel'
      response.body[attribute] = instance["kernelId"]
    when 'ramdisk'
      response.body[attribute] = instance["ramdiskId"]
    when 'disableApiTermination'
      response.body[attribute] = false
    when 'instanceInitiatedShutdownBehavior'
      response.body['instanceInitiatedShutdownBehavior'] = 'stop'
    when 'sourceDestCheck'
      response.body[attribute] = true
    when 'sriovNetSupport'
      response.body[attribute] = 'simple'
    else
      response.body[attribute] = instance[attribute]
    end
  response
  else
    raise Fog::AWS::Compute::NotFound.new("The Instance '#{instance_id}' does not exist")
  end
end

#describe_instance_status(filters = {}) ⇒ Object



32
33
34
35
36
37
38
39
40
41
42
# File 'lib/fog/aws/requests/compute/describe_instance_status.rb', line 32

def describe_instance_status(filters = {})
  response = Excon::Response.new
  response.status = 200

  response.body = {
    'instanceStatusSet' => [],
    'requestId' => Fog::AWS::Mock.request_id
  }

  response
end

#describe_instances(filters = {}) ⇒ Object



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
# File 'lib/fog/aws/requests/compute/describe_instances.rb', line 90

def describe_instances(filters = {})
  unless filters.is_a?(Hash)
    Fog::Logger.deprecation("describe_instances with #{filters.class} param is deprecated, use describe_instances('instance-id' => []) instead [light_black](#{caller.first})[/]")
    filters = {'instance-id' => [*filters]}
  end

  response = Excon::Response.new

  instance_set = self.data[:instances].values
  instance_set = apply_tag_filters(instance_set, filters, 'instanceId')

  aliases = {
    'architecture'             => 'architecture',
    'availability-zone'        => 'availabilityZone',
    'client-token'             => 'clientToken',
    'dns-name'                 => 'dnsName',
    'group-id'                 => 'groupId',
    'image-id'                 => 'imageId',
    'instance-id'              => 'instanceId',
    'instance-lifecycle'       => 'instanceLifecycle',
    'instance-type'            => 'instanceType',
    'ip-address'               => 'ipAddress',
    'kernel-id'                => 'kernelId',
    'key-name'                 => 'key-name',
    'launch-index'             => 'launchIndex',
    'launch-time'              => 'launchTime',
    'monitoring-state'         => 'monitoringState',
    'owner-id'                 => 'ownerId',
    'placement-group-name'     => 'placementGroupName',
    'platform'                 => 'platform',
    'private-dns-name'         => 'privateDnsName',
    'private-ip-address'       => 'privateIpAddress',
    'product-code'             => 'productCode',
    'ramdisk-id'               => 'ramdiskId',
    'reason'                   => 'reason',
    'requester-id'             => 'requesterId',
    'reservation-id'           => 'reservationId',
    'root-device-name'         => 'rootDeviceName',
    'root-device-type'         => 'rootDeviceType',
    'spot-instance-request-id' => 'spotInstanceRequestId',
    'subnet-id'                => 'subnetId',
    'virtualization-type'      => 'virtualizationType',
    'vpc-id'                   => 'vpcId'
  }
  block_device_mapping_aliases = {
    'attach-time'           => 'attachTime',
    'delete-on-termination' => 'deleteOnTermination',
    'device-name'           => 'deviceName',
    'status'                => 'status',
    'volume-id'             => 'volumeId',
  }
  instance_state_aliases = {
    'code' => 'code',
    'name' => 'name'
  }
  state_reason_aliases = {
    'code'    => 'code',
    'message' => 'message'
  }
  for filter_key, filter_value in filters
    if block_device_mapping_key = filter_key.split('block-device-mapping.')[1]
      aliased_key = block_device_mapping_aliases[block_device_mapping_key]
      instance_set = instance_set.reject{|instance| !instance['blockDeviceMapping'].find {|block_device_mapping| [*filter_value].include?(block_device_mapping[aliased_key])}}
    elsif instance_state_key = filter_key.split('instance-state-')[1]
      aliased_key = instance_state_aliases[instance_state_key]
      instance_set = instance_set.reject{|instance| ![*filter_value].include?(instance['instanceState'][aliased_key])}
    elsif state_reason_key = filter_key.split('state-reason-')[1]
      aliased_key = state_reason_aliases[state_reason_key]
      instance_set = instance_set.reject{|instance| ![*filter_value].include?(instance['stateReason'][aliased_key])}
    elsif filter_key == "availability-zone"
      aliased_key = aliases[filter_key]
      instance_set = instance_set.reject{|instance| ![*filter_value].include?(instance['placement'][aliased_key])}
    elsif filter_key == "group-name"
      instance_set = instance_set.reject {|instance| !instance['groupSet'].include?(filter_value)}
    elsif filter_key == "group-id"
      group_ids = [*filter_value]
      security_group_names = self.data[:security_groups].values.select { |sg| group_ids.include?(sg['groupId']) }.map { |sg| sg['groupName'] }
      instance_set = instance_set.reject {|instance| (security_group_names & instance['groupSet']).empty?}
    else
      aliased_key = aliases[filter_key]
      instance_set = instance_set.reject {|instance| ![*filter_value].include?(instance[aliased_key])}
    end
  end

  brand_new_instances = instance_set.select do |instance|
    instance['instanceState']['name'] == 'pending' &&
      Time.now - instance['launchTime'] < Fog::Mock.delay * 2
  end

  # Error if filtering for a brand new instance directly
  if (filters['instance-id'] || filters['instanceId']) && !brand_new_instances.empty?
    raise Fog::AWS::Compute::NotFound.new("The instance ID '#{brand_new_instances.first['instanceId']}' does not exist")
  end

  # Otherwise don't include it in the list
  instance_set = instance_set.reject {|instance| brand_new_instances.include?(instance) }

  response.status = 200
  reservation_set = {}

  instance_set.each do |instance|
    case instance['instanceState']['name']
    when 'pending'
      if Time.now - instance['launchTime'] >= Fog::Mock.delay * 2
        instance['ipAddress']         = Fog::AWS::Mock.ip_address
        instance['originalIpAddress'] = instance['ipAddress']
        instance['dnsName']           = Fog::AWS::Mock.dns_name_for(instance['ipAddress'])
        instance['instanceState']     = { 'code' => 16, 'name' => 'running' }
      end
    when 'rebooting'
      instance['instanceState'] = { 'code' => 16, 'name' => 'running' }
    when 'stopping'
      instance['instanceState'] = { 'code' => 0, 'name' => 'stopped' }
      instance['stateReason'] = { 'code' => 0 }
    when 'shutting-down'
      if Time.now - self.data[:deleted_at][instance['instanceId']] >= Fog::Mock.delay * 2
        self.data[:deleted_at].delete(instance['instanceId'])
        self.data[:instances].delete(instance['instanceId'])
      elsif Time.now - self.data[:deleted_at][instance['instanceId']] >= Fog::Mock.delay
        instance['instanceState'] = { 'code' => 48, 'name' => 'terminating' }
      end
    when 'terminating'
      if Time.now - self.data[:deleted_at][instance['instanceId']] >= Fog::Mock.delay
        self.data[:deleted_at].delete(instance['instanceId'])
        self.data[:instances].delete(instance['instanceId'])
      end
    end

    if self.data[:instances][instance['instanceId']]

      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'],
        'groupIds'      => instance['groupIds'],
        'instancesSet'  => [],
        'ownerId'       => instance['ownerId'],
        'reservationId' => instance['reservationId']
      }
      reservation_set[instance['reservationId']]['instancesSet'] << instance.reject{|key,value| !['amiLaunchIndex', 'architecture', 'blockDeviceMapping', 'clientToken', 'dnsName', 'ebsOptimized', 'hypervisor', 'iamInstanceProfile', 'imageId', 'instanceId', 'instanceState', 'instanceType', 'ipAddress', 'kernelId', 'keyName', 'launchTime', 'monitoring', 'networkInterfaces', 'ownerId', 'placement', 'platform', 'privateDnsName', 'privateIpAddress', 'productCodes', 'ramdiskId', 'reason', 'rootDeviceName', 'rootDeviceType', 'spotInstanceRequestId', 'stateReason', 'subnetId', 'virtualizationType'].include?(key)}.merge('tagSet' => self.data[:tag_sets][instance['instanceId']])
    end
  end

  response.body = {
    'requestId'       => Fog::AWS::Mock.request_id,
    'reservationSet' => reservation_set.values
  }
  response
end

#describe_internet_gateways(filters = {}) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/fog/aws/requests/compute/describe_internet_gateways.rb', line 41

def describe_internet_gateways(filters = {})
  internet_gateways = self.data[:internet_gateways].values

  if filters['internet-gateway-id']
    internet_gateways = internet_gateways.reject {|internet_gateway| internet_gateway['internetGatewayId'] != filters['internet-gateway-id']}
  end

  Excon::Response.new(
    :status => 200,
    :body   => {
      'requestId'           => Fog::AWS::Mock.request_id,
      'internetGatewaySet'  => internet_gateways
    }
  )
end

#describe_key_pairs(filters = {}) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/fog/aws/requests/compute/describe_key_pairs.rb', line 36

def describe_key_pairs(filters = {})
  unless filters.is_a?(Hash)
    Fog::Logger.deprecation("describe_key_pairs with #{filters.class} param is deprecated, use describe_key_pairs('key-name' => []) instead [light_black](#{caller.first})[/]")
    filters = {'key-name' => [*filters]}
  end

  response = Excon::Response.new

  key_set = self.data[:key_pairs].values

  aliases = {'fingerprint' => 'keyFingerprint', 'key-name' => 'keyName'}
  for filter_key, filter_value in filters
    aliased_key = aliases[filter_key]
    key_set = key_set.reject{|key_pair| ![*filter_value].include?(key_pair[aliased_key])}
  end

  response.status = 200
  response.body = {
    'requestId' => Fog::AWS::Mock.request_id,
    'keySet'    => key_set.map do |key_pair|
      key_pair.reject {|key,value| !['keyFingerprint', 'keyName'].include?(key)}
    end
  }
  response
end

#describe_network_acls(filters = {}) ⇒ Object



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/fog/aws/requests/compute/describe_network_acls.rb', line 52

def describe_network_acls(filters = {})
  response = Excon::Response.new

  network_acls = self.data[:network_acls].values
  network_acls = apply_tag_filters(network_acls, filters, 'networkAclId')

  aliases = {
    'vpc-id'         => 'vpcId',
    'network-acl-id' => 'networkAclId',
    'default'        => 'default',
  }
  association_aliases = {
    'association-id' => 'networkAclAssociationId',
    'network-acl-id' => 'networkAclId',
    'subnet-id'      => 'subnetId',
  }
  entry_aliases = {
    'cidr'        => 'cidrBlock',
    'egress'      => 'egress',
    'rule-action' => 'ruleAction',
    'rule-number' => 'ruleNumber',
    'protocol'    => 'protocol'
  }
  for filter_key, filter_value in filters
    filter_key = filter_key.to_s
    if association_key = filter_key.split('association.')[1]
      aliased_key = association_aliases[association_key]
      network_acls = network_acls.reject{|nacl| !nacl['associationSet'].find {|association| [*filter_value].include?(association[aliased_key])}}
    elsif entry_key = filter_key.split('entry.icmp.')[1]
      network_acls = network_acls.reject{|nacl| !nacl['entrySet'].find {|association| [*filter_value].include?(association['icmpTypeCode'][entry_key])}}
    elsif entry_key = filter_key.split('entry.port-range.')[1]
      network_acls = network_acls.reject{|nacl| !nacl['entrySet'].find {|association| [*filter_value].include?(association['portRange'][entry_key])}}
    elsif entry_key = filter_key.split('entry.')[1]
      aliased_key = entry_aliases[entry_key]
      network_acls = network_acls.reject{|nacl| !nacl['entrySet'].find {|association| [*filter_value].include?(association[aliased_key])}}
    else
      aliased_key = aliases[filter_key]
      network_acls = network_acls.reject{|nacl| ![*filter_value].include?(nacl[aliased_key])}
    end
  end

  network_acls.each do |acl|
    tags = self.data[:tag_sets][acl['networkAclId']]
    acl.merge!('tagSet' => tags) if tags
  end

  response.status = 200
  response.body = {
    'requestId'     => Fog::AWS::Mock.request_id,
    'networkAclSet' => network_acls
  }
  response
end

#describe_network_interface_attribute(network_interface_id, attribute) ⇒ Object



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/fog/aws/requests/compute/describe_network_interface_attribute.rb', line 43

def describe_network_interface_attribute(network_interface_id, attribute)
  response = Excon::Response.new
  network_interface = self.data[:network_interfaces][network_interface_id]


  unless network_interface
    raise Fog::AWS::Compute::NotFound.new("The network interface '#{network_interface_id}' does not exist")
  end

  response.status = 200
  response.body = {
    'requestId'          => Fog::AWS::Mock.request_id,
    'networkInterfaceId' => network_interface_id
  }
  case attribute
  when 'description', 'groupSet', 'sourceDestCheck', 'attachment'
    response.body[attribute] = network_interface[attribute]
  else
    raise Fog::AWS::Compute::Error.new("Illegal attribute '#{attribute}' specified")
  end
  response
end

#describe_network_interfaces(filters = {}) ⇒ Object



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/fog/aws/requests/compute/describe_network_interfaces.rb', line 66

def describe_network_interfaces(filters = {})
  response = Excon::Response.new

  network_interface_info = self.data[:network_interfaces].values

  if subnet_filter = filters.delete('subnet-id')
    filters['subnetId'] = subnet_filter
  end

  for filter_key, filter_value in filters
    network_interface_info = network_interface_info.reject{|nic| ![*filter_value].include?(nic[filter_key])}
  end

  response.status = 200
  response.body = {
    'requestId'           => Fog::AWS::Mock.request_id,
    'networkInterfaceSet' => network_interface_info
  }
  response
end

#describe_regions(filters = {}) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/fog/aws/requests/compute/describe_regions.rb', line 36

def describe_regions(filters = {})
  unless filters.is_a?(Hash)
    Fog::Logger.deprecation("describe_regions with #{filters.class} param is deprecated, use describe_regions('region-name' => []) instead [light_black](#{caller.first})[/]")
    filters = {'region-name' => [*filters]}
  end

  response = Excon::Response.new
  region_info = [
    {"regionName"=>"eu-west-1", "regionEndpoint"=>"eu-west-1.ec2.amazonaws.com"},
    {"regionName"=>"us-east-1", "regionEndpoint"=>"us-east-1.ec2.amazonaws.com"}
  ]

  aliases = {'region-name' => 'regionName', 'endpoint' => 'regionEndpoint'}
  for filter_key, filter_value in filters
    aliased_key = aliases[filter_key]
    region_info = region_info.reject{|region| ![*filter_value].include?(region[aliased_key])}
  end

  response.status = 200
  response.body = {
    'requestId'   => Fog::AWS::Mock.request_id,
    'regionInfo'  => region_info
  }
  response
end

#describe_reserved_instances(filters = {}) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
# File 'lib/fog/aws/requests/compute/describe_reserved_instances.rb', line 49

def describe_reserved_instances(filters = {})
  response = Excon::Response.new
  response.status = 200

  response.body = {
    'reservedInstancesSet' => self.data[:reserved_instances].values,
    'requestId' => Fog::AWS::Mock.request_id
  }

  response
end

#describe_reserved_instances_offerings(filters = {}) ⇒ Object



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/fog/aws/requests/compute/describe_reserved_instances_offerings.rb', line 56

def describe_reserved_instances_offerings(filters = {})
  response = Excon::Response.new
  response.status = 200

  self.data[:reserved_instances_offerings] ||= [{
    'reservedInstancesOfferingId' => Fog::AWS::Mock.reserved_instances_offering_id,
    'instanceType'                => 'm1.small',
    'availabilityZone'            => 'us-east-1d',
    'duration'                    => 31536000,
    'fixedPrice'                  => 350.0,
    'offeringType'                => 'Medium Utilization',
    'usagePrice'                  => 0.03,
    'productDescription'          => 'Linux/UNIX',
    'instanceTenancy'             => 'default',
    'currencyCode'                => 'USD'
  }]

  response.body = {
    'reservedInstancesOfferingsSet' => self.data[:reserved_instances_offerings],
    'requestId' => Fog::AWS::Mock.request_id,
    'nextToken' => (0...64).map { ('a'..'z').to_a[rand(26)] }.join
  }

  response
end

#describe_route_tables(filters = {}) ⇒ Object



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/fog/aws/requests/compute/describe_route_tables.rb', line 56

def describe_route_tables(filters = {})
  unless filters.is_a?(Hash)
    Fog::Logger.deprecation("describe_route_tables with #{filters.class} param is deprecated, use describe_route_tables('route-table-id' => []) instead [light_black](#{caller.first})[/]")
    filters = {'route-table-id' => [*filters]}
  end

  display_routes = self.data[:route_tables].dup

  aliases = {
    'route-table-id'  => 'routeTableId',
    'vpc-id'          => 'vpcId'
  }

  for filter_key, filter_value in filters
    filter_attribute = aliases[filter_key]
    case filter_attribute
    when 'routeTableId', 'vpcId'
      display_routes.reject! { |routetable| routetable[filter_attribute] != filter_value }
    end
  end

  display_routes.each do |route|
    tags = self.data[:tag_sets][route['routeTableId']]
    route.merge!('tagSet' => tags) if tags
  end

  Excon::Response.new(
    :status => 200,
    :body   => {
      'requestId' => Fog::AWS::Mock.request_id,
      'routeTableSet'    => display_routes
    }
  )
end

#describe_security_groups(filters = {}) ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/fog/aws/requests/compute/describe_security_groups.rb', line 58

def describe_security_groups(filters = {})
  unless filters.is_a?(Hash)
    Fog::Logger.deprecation("describe_security_groups with #{filters.class} param is deprecated, use describe_security_groups('group-name' => []) instead [light_black](#{caller.first})[/]")
    filters = {'group-name' => [*filters]}
  end

  response = Excon::Response.new

  security_group_info = self.data[:security_groups].reject { |k,v| k['amazon-elb-sg'] }.values

  aliases = {
    'description' => 'groupDescription',
    'group-name'  => 'groupName',
    'group-id'    => 'groupId',
    'owner-id'    => 'ownerId'
  }
  permission_aliases = {
    'cidr'      => 'cidrIp',
    'from-port' => 'fromPort',
    'protocol'  => 'ipProtocol',
    'to-port'   => 'toPort'
  }

  security_group_groups = lambda do |security_group|
    (security_group['ipPermissions'] || []).map do |permission|
      permission['groups']
    end.flatten.compact.uniq
  end

  for filter_key, filter_value in filters
    if permission_key = filter_key.split('ip-permission.')[1]
      if permission_key == 'group-name'
        security_group_info = security_group_info.reject do |security_group|
          !security_group_groups.call(security_group).find do |group|
            [*filter_value].include?(group['groupName'])
          end
        end
      elsif permission_key == 'group-id'
        security_group_info = security_group_info.reject do |security_group|
          !security_group_groups.call(security_group).find do |group|
            [*filter_value].include?(group['groupId'])
          end
        end
      elsif permission_key == 'user-id'
        security_group_info = security_group_info.reject do |security_group|
          !security_group_groups.call(security_group).find do |group|
            [*filter_value].include?(group['userId'])
          end
        end
      else
        aliased_key = permission_aliases[filter_key]
        security_group_info = security_group_info.reject do |security_group|
          !security_group['ipPermissions'].find do |permission|
            [*filter_value].include?(permission[aliased_key])
          end
        end
      end
    else
      aliased_key = aliases[filter_key]
      security_group_info = security_group_info.reject do |security_group|
        ![*filter_value].include?(security_group[aliased_key])
      end
    end
  end

  response.status = 200
  response.body = {
    'requestId'         => Fog::AWS::Mock.request_id,
    'securityGroupInfo' => security_group_info
  }
  response
end

#describe_snapshots(filters = {}, options = {}) ⇒ Object



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/fog/aws/requests/compute/describe_snapshots.rb', line 53

def describe_snapshots(filters = {}, options = {})
  unless filters.is_a?(Hash)
    Fog::Logger.deprecation("describe_snapshots with #{filters.class} param is deprecated, use describe_snapshots('snapshot-id' => []) instead [light_black](#{caller.first})[/]")
    filters = {'snapshot-id' => [*filters]}
  end
  unless options.empty?
    Fog::Logger.deprecation("describe_snapshots with a second param is deprecated, use describe_snapshots(options) instead [light_black](#{caller.first})[/]")
  end

  response = Excon::Response.new

  snapshot_set = self.data[:snapshots].values

  if filters.delete('owner-alias')
    Fog::Logger.warning("describe_snapshots with owner-alias is not mocked [light_black](#{caller.first})[/]")
  end
  if (restorable_by = filters.delete('RestorableBy')) && restorable_by != 'self'
    Fog::Logger.warning("describe_snapshots with RestorableBy other than 'self' (wanted #{restorable_by.inspect}) is not mocked [light_black](#{caller.first})[/]")
  end

  snapshot_set = apply_tag_filters(snapshot_set, filters, 'snapshotId')

  aliases = {
    'description' => 'description',
    'encrypted'   => 'encrypted',
    'owner-id'    => 'ownerId',
    'progress'    => 'progress',
    'snapshot-id' => 'snapshotId',
    'start-time'  => 'startTime',
    'status'      => 'status',
    'volume-id'   => 'volumeId',
    'volume-size' => 'volumeSize'
  }

  for filter_key, filter_value in filters
    aliased_key = aliases[filter_key]
    snapshot_set = snapshot_set.reject{|snapshot| ![*filter_value].include?(snapshot[aliased_key])}
  end

  snapshot_set.each do |snapshot|
    case snapshot['status']
    when 'in progress', 'pending'
      if Time.now - snapshot['startTime'] >= Fog::Mock.delay * 2
        snapshot['progress']  = '100%'
        snapshot['status']    = 'completed'
      elsif Time.now - snapshot['startTime'] >= Fog::Mock.delay
        snapshot['progress']  = '50%'
        snapshot['status']    = 'in progress'
      else
        snapshot['progress']  = '0%'
        snapshot['status']    = 'in progress'
      end
    end
  end

  snapshot_set = snapshot_set.map {|snapshot| snapshot.merge('tagSet' => self.data[:tag_sets][snapshot['snapshotId']]) }

  response.status = 200
  response.body = {
    'requestId' => Fog::AWS::Mock.request_id,
    'snapshotSet' => snapshot_set
  }
  response
end

#describe_spot_instance_requests(filters = {}) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/fog/aws/requests/compute/describe_spot_instance_requests.rb', line 46

def describe_spot_instance_requests(filters = {})
  response = Excon::Response.new
  spot_requests = self.data[:spot_requests].values

  if id = Array(filters['spot-instance-request-id']).first
    spot_requests = spot_requests.select { |r| r['spotInstanceRequestId'] == id }
  end

  spot_requests.select { |r| r['instanceId'].nil? }.each do |request|
    run_instance_options = {
      'BlockDeviceMapping'    => request['launchSpecification']['blockDeviceMapping'],
      'EbsOptimized'          => request['launchSpecification']['ebsOptimized'],
      'KeyName'               => request['launchSpecification']['keyName'],
      'SecurityGroupId'       => request['launchSpecification']['groupSet'].first,
      'SpotInstanceRequestId' => request['spotInstanceRequestId'],
      'SubnetId'              => request['launchSpecification']['subnetId']
    }
    instances = run_instances(request['launchSpecification']['imageId'], 1,1, run_instance_options).body['instancesSet']

    request['instanceId'] = instances.first['instanceId']
    request['state'] = 'active'
    request['fault'] = {'code' => 'fulfilled', 'message' => 'Your Spot request is fulfilled.'}
    request['launchedAvailabilityZone'] = instances.first['placement']['availabilityZone']

    self.data[:spot_requests][request['spotInstanceRequestId']] = request
  end

  response.body = {'spotInstanceRequestSet' => spot_requests, 'requestId' => Fog::AWS::Mock.request_id}
  response
end

#describe_spot_price_history(filters = {}) ⇒ Object



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/fog/aws/requests/compute/describe_spot_price_history.rb', line 61

def describe_spot_price_history(filters = {})
  params = {}
  spot_price_history_set = []

  response = Excon::Response.new
  response.status = 200

  for key in %w(StartTime EndTime NextToken)
    if filters.is_a?(Hash) && filters.key?(key)
      Fog::Logger.warning("#{key} filters are not yet mocked [light_black](#{caller.first})[/]")
      Fog::Mock.not_implemented
    end
  end

  for key in %w(AvailabilityZone MaxResults)
    if filters.is_a?(Hash) && filters.key?(key)
      params[key] = filters.delete(key)
    end
  end

  all_zones = describe_availability_zones.body['availabilityZoneInfo'].map { |z| z['zoneName'] }
  zones = params['AvailabilityZone']
  if (!zones.nil? && !all_zones.include?([*zones].shuffle.first))
    az_error = "InvalidParameterValue => Invalid availability zone: [#{zones}]"
    raise Fog::AWS::Compute::Error, az_error
  end
  zones = all_zones if zones.nil?

  max_results = params['MaxResults'] || Fog::Mock.random_numbers(3).to_i
  if !(max_results.is_a?(Integer) && max_results > 0)
    max_results_error = "InvalidParameterValue => Invalid value '#{max_results}' for maxResults"
    raise Fog::AWS::Compute::Error, max_results_error
  end

  all_instance_types = flavors.map { |f| f.id }
  instance_types = filters.delete('InstanceType') || all_instance_types
  product_descriptions = filters.delete('ProductDescription') || Fog::AWS::Mock.spot_product_descriptions

  max_results.times do
    spot_price_history_set << {
      'instanceType'       => [*instance_types].shuffle.first,
      'productDescription' => [*product_descriptions].shuffle.first,
      'spotPrice'          => ((rand + [0 , 1].shuffle.first) * 10000).round / 10000.0,
      'timestamp'          => Time.now - (1 + rand(86400)),
      'availabilityZone'   => [*zones].shuffle.first
    }
  end
  spot_price_history_set.sort! { |x,y| x['timestamp'] <=> y['timestamp'] }

  response.body = {
    'spotPriceHistorySet' => spot_price_history_set,
    'requestId'           => Fog::AWS::Mock.request_id,
    'nextToken'           => nil
  }
  response
end

#describe_subnets(filters = {}) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/fog/aws/requests/compute/describe_subnets.rb', line 46

def describe_subnets(filters = {})
  subnets = self.data[:subnets]

  # Transition from pending to available
  subnets.each do |subnet|
    case subnet['state']
      when 'pending'
        subnet['state'] = 'available'
    end
  end

  if filters['subnet-id']
    subnets = subnets.reject {|subnet| subnet['subnetId'] != filters['subnet-id']}
  end

  Excon::Response.new(
    :status => 200,
    :body   => {
      'requestId' => Fog::AWS::Mock.request_id,
      'subnetSet' => subnets
    }
  )
end

#describe_tags(filters = {}) ⇒ Object



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/fog/aws/requests/compute/describe_tags.rb', line 34

def describe_tags(filters = {})
  response = Excon::Response.new

  tag_set = deep_clone(self.data[:tags])

  aliases = {
    'key'               => 'key',
    'resource-id'       => 'resourceId',
    'resource-type'     => 'resourceType',
    'value'             => 'value'
  }

  for filter_key, filter_value in filters
    filter_attribute = aliases[filter_key]
    case filter_attribute
    when 'key'
      tag_set.reject! { |k,_| k != filter_value }
    when 'value'
      tag_set.each { |k,values| values.reject! { |v, _| v != filter_value } }
    when 'resourceId'
      filter_resources(tag_set, 'resourceId', filter_value)
    when 'resourceType'
      filter_resources(tag_set, 'resourceType', filter_value)
    end
  end

  tagged_resources = []
  tag_set.each do |key, values|
    values.each do |value, resources|
      resources.each do |resource|
        tagged_resources << resource.merge({
          'key' => key,
          'value' => value
        })
      end
    end
  end

  response.status = 200
  response.body = {
    'requestId'       => Fog::AWS::Mock.request_id,
    'tagSet'          => tagged_resources
  }
  response
end

#describe_volume_status(filters = {}) ⇒ Object



29
30
31
32
33
34
35
36
37
38
39
# File 'lib/fog/aws/requests/compute/describe_volume_status.rb', line 29

def describe_volume_status(filters = {})
  response = Excon::Response.new
  response.status = 200

  response.body = {
    'volumeStatusSet' => [],
    'requestId' => Fog::AWS::Mock.request_id
  }

  response
end

#describe_volumes(filters = {}) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/fog/aws/requests/compute/describe_volumes.rb', line 49

def describe_volumes(filters = {})
  unless filters.is_a?(Hash)
    Fog::Logger.deprecation("describe_volumes with #{filters.class} param is deprecated, use describe_volumes('volume-id' => []) instead [light_black](#{caller.first})[/]")
    filters = {'volume-id' => [*filters]}
  end

  response = Excon::Response.new

  volume_set = self.data[:volumes].values
  volume_set = apply_tag_filters(volume_set, filters, 'volumeId')

  aliases = {
    'availability-zone' => 'availabilityZone',
    'create-time' => 'createTime',
    'encrypted' => 'encrypted',
    'size' => 'size',
    'snapshot-id' => 'snapshotId',
    'status' => 'status',
    'volume-id' => 'volumeId'
  }
  attachment_aliases = {
    'attach-time' => 'attachTime',
    'delete-on-termination' => 'deleteOnTermination',
    'device'      => 'device',
    'instance-id' => 'instanceId',
    'status'      => 'status'
  }

  for filter_key, filter_value in filters
    if attachment_key = filter_key.split('attachment.')[1]
      aliased_key = attachment_aliases[filter_key]
      volume_set = volume_set.reject{|volume| !volume['attachmentSet'].find {|attachment| [*filter_value].include?(attachment[aliased_key])}}
    else
      aliased_key = aliases[filter_key]
      volume_set = volume_set.reject{|volume| ![*filter_value].include?(volume[aliased_key])}
    end
  end

  volume_set.each do |volume|
    case volume['status']
    when 'attaching'
      if Time.now - volume['attachmentSet'].first['attachTime'] >= Fog::Mock.delay
        volume['attachmentSet'].first['status'] = 'in-use'
        volume['status'] = 'in-use'
      end
    when 'creating'
      if Time.now - volume['createTime'] >= Fog::Mock.delay
        volume['status'] = 'available'
      end
    when 'deleting'
      if Time.now - self.data[:deleted_at][volume['volumeId']] >= Fog::Mock.delay
        self.data[:deleted_at].delete(volume['volumeId'])
        self.data[:volumes].delete(volume['volumeId'])
      end
    end
  end
  volume_set = volume_set.reject {|volume| !self.data[:volumes][volume['volumeId']]}
  volume_set = volume_set.map {|volume| volume.merge('tagSet' => self.data[:tag_sets][volume['volumeId']]) }

  response.status = 200
  response.body = {
    'requestId' => Fog::AWS::Mock.request_id,
    'volumeSet' => volume_set
  }
  response
end

#describe_volumes_modifications(filters = {}) ⇒ Object



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/fog/aws/requests/compute/describe_volumes_modifications.rb', line 43

def describe_volumes_modifications(filters = {})
  response = Excon::Response.new

  modification_set = self.data[:volume_modifications].values

  aliases = {
    'volume-id'            => 'volumeId',
    'modification-state'   => 'modificationState',
    'target-size'          => 'targetSize',
    'target-iops'          => 'targetIops',
    'target-volume-type'   => 'targetVolumeType',
    'original-size'        => 'originalSize',
    'original-iops'        => 'originalIops',
    'original-volume-type' => 'originalVolumeType',
    'start-time'           => 'startTime'
  }

  attribute_aliases = {
    'targetSize'       => 'size',
    'targetVolumeType' => 'volumeType',
    'targetIops'       => 'iops'
  }

  for filter_key, filter_value in filters
    aliased_key = aliases[filter_key]
    modification_set = modification_set.reject { |m| ![*filter_value].include?(m[aliased_key]) }
  end

  modification_set.each do |modification|
    case modification['modificationState']
    when 'modifying'
      volume = self.data[:volumes][modification['volumeId']]
      modification['modificationState'] = 'optimizing'
      %w(targetSize targetIops targetVolumeType).each do |attribute|
        aliased_attribute = attribute_aliases[attribute]
        volume[aliased_attribute] = modification[attribute] if modification[attribute]
      end
      self.data[:volumes][modification['volumeId']] = volume
    when 'optimizing'
      modification['modificationState'] = 'completed'
      modification['endTime']           = Time.now
    end
  end

  response.body = {'requestId' => Fog::AWS::Mock.request_id, 'volumeModificationSet' => modification_set}
  response
end

#describe_vpc_attribute(vpc_id, attribute) ⇒ Object



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/fog/aws/requests/compute/describe_vpc_attribute.rb', line 32

def describe_vpc_attribute(vpc_id, attribute)
  response = Excon::Response.new
  if vpc = self.data[:vpcs].find{ |v| v['vpcId'] == vpc_id }
    response.status = 200
    response.body = {
      'requestId' => Fog::AWS::Mock.request_id,
      'vpcId'     => vpc_id
    }

    case attribute
    when 'enableDnsSupport', 'enableDnsHostnames'
      response.body[attribute] = vpc[attribute]
    else
      raise Fog::AWS::Compute::Error.new("Illegal attribute '#{attribute}' specified")
    end
    response
  else
    raise Fog::AWS::Compute::NotFound.new("The VPC '#{vpc_id}' does not exist")
  end
end


35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/fog/aws/requests/compute/describe_vpc_classic_link.rb', line 35

def describe_vpc_classic_link(options={})
  response = Excon::Response.new
  vpcs = self.data[:vpcs]
  if vpc_ids = options[:vpc_ids]
    vpcs = vpc_ids.collect do |vpc_id|
      vpc = vpcs.find{ |v| v['vpcId'] == vpc_id }
      raise Fog::AWS::Compute::NotFound.new("The VPC '#{vpc_id}' does not exist") unless vpc
      vpc
    end
  end
  vpcs = apply_tag_filters(vpcs, options[:filters], 'vpcId') if options[:filters]

  response.status = 200
  vpc_data = vpcs.collect do |vpc|
    {
      'vpcId' => vpc['vpcId'],
      'classicLinkEnabled' => vpc['classicLinkEnabled'],
      'tagSet' => self.data[:tag_sets][vpc['vpcId']] || {}
    }
  end
  response.body = {
    'requestId' => Fog::AWS::Mock.request_id,
    'vpcSet' => vpc_data
  }
  response
end


38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/fog/aws/requests/compute/describe_vpc_classic_link_dns_support.rb', line 38

def describe_vpc_classic_link_dns_support(options={})
  response = Excon::Response.new

  vpcs = self.data[:vpcs]

  if options[:vpc_ids]
    vpcs = vpcs.select { |v| options[:vpc_ids].include?(v['vpcId']) }
  end

  response.body = {'vpcs' => vpcs.map { |v| {"vpcId" => v['vpcId'], "classicLinkDnsSupported" => v['classicLinkDnsSupport']} } }
  response
end

#describe_vpcs(filters = {}) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/fog/aws/requests/compute/describe_vpcs.rb', line 42

def describe_vpcs(filters = {})
  vpcs = self.data[:vpcs]
  vpcs = apply_tag_filters(vpcs, filters, 'vpcId')

  # Transition from pending to available
  vpcs.each do |vpc|
    case vpc['state']
      when 'pending'
        vpc['state'] = 'available'
    end
  end

  if filters['vpc-id']
    vpcs = vpcs.reject {|vpc| vpc['vpcId'] != filters['vpc-id']}
  end

  vpcs.each do |vpc|
    tags = self.data[:tag_sets][vpc['vpcId']]
    vpc.merge!('tagSet' => tags) if tags
  end

  Excon::Response.new(
    :status => 200,
    :body   => {
      'requestId' => Fog::AWS::Mock.request_id,
      'vpcSet'    => vpcs
    }
  )
end


34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/fog/aws/requests/compute/detach_classic_link_vpc.rb', line 34

def detach_classic_link_vpc(instance_id, vpc_id, dry_run=false)
  response = Excon::Response.new
  vpc = self.data[:vpcs].find{ |v| v['vpcId'] == vpc_id }
  instance = self.data[:instances][instance_id]
  if vpc && instance
    response.status = 200
    response.body = {
      'requestId' => Fog::AWS::Mock.request_id,
      'return'    => true
    }
    unless dry_run
      instance['classicLinkSecurityGroups'] = nil
      instance['classicLinkVpcId'] = nil
    end
    response
  elsif !instance
    raise Fog::AWS::Compute::NotFound.new("The instance ID '#{instance_id}' does not exist.")
  elsif !vpc
    raise Fog::AWS::Compute::NotFound.new("The VPC '#{vpc_id}' does not exist.")
  end
end

#detach_internet_gateway(internet_gateway_id, vpc_id) ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/fog/aws/requests/compute/detach_internet_gateway.rb', line 31

def detach_internet_gateway(internet_gateway_id, vpc_id)
  response = Excon::Response.new
  if internet_gateway_id && vpc_id
    response.status = 200
    response.body = {
      'requestId' => Fog::AWS::Mock.request_id,
      'return' => true
    }
    response
  else
    if !internet_gateway_id
      message << 'The request must contain the parameter internet_gateway_id'
    elsif !vpc_id
      message << 'The request must contain the parameter vpc_id'
    end
    raise Fog::AWS::Compute::Error.new(message)
  end
end

#detach_network_interface(attachment_id, force = false) ⇒ Object



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/fog/aws/requests/compute/detach_network_interface.rb', line 30

def detach_network_interface(attachment_id, force = false)
  response = Excon::Response.new
  nic_id = self.data[:network_interfaces].select { |k,v| v['attachment']['attachmentId'] == attachment_id} .first.first
  if nic_id
    self.data[:network_interfaces][nic_id]["attachment"] = {}
    response.status = 200
    response.body = {
      'requestId' => Fog::AWS::Mock.request_id,
      'return'    => true
    }
    response
  else
    raise Fog::AWS::Compute::NotFound.new("The network interface '#{network_interface_id}' does not exist")
  end
end

#detach_volume(volume_id, options = {}) ⇒ Object



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/fog/aws/requests/compute/detach_volume.rb', line 38

def detach_volume(volume_id, options = {})
  response = Excon::Response.new
  response.status = 200
  if (volume = self.data[:volumes][volume_id])
    if !volume['attachmentSet'].empty?
      data = volume['attachmentSet'].pop
      volume['status'] = 'available'
      response.status = 200
      response.body = {
        'requestId' => Fog::AWS::Mock.request_id
      }.merge!(data)
      response
    else
      # real response has spacing issue below
      raise Fog::AWS::Compute::Error.new("IncorrectState => Volume '#{volume_id}'is in the 'available' state.")
    end
  else
    raise Fog::AWS::Compute::NotFound.new("The volume '#{volume_id}' does not exist.")
  end
end

#disable_ec2_classicObject



374
375
376
# File 'lib/fog/aws/compute.rb', line 374

def disable_ec2_classic
  set_supported_platforms(%w[VPC])
end


30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/fog/aws/requests/compute/disable_vpc_classic_link.rb', line 30

def disable_vpc_classic_link(vpc_id, dry_run=false)
  response = Excon::Response.new
  if vpc = self.data[:vpcs].find{ |v| v['vpcId'] == vpc_id }
    response.status = 200
    response.body = {
      'requestId' => Fog::AWS::Mock.request_id,
      'return'    => true
    }
    vpc['classicLinkEnabled'] = false unless dry_run
    response
  else
    raise Fog::AWS::Compute::NotFound.new("The VPC '#{vpc_id}' does not exist")
  end
end


30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/fog/aws/requests/compute/disable_vpc_classic_link_dns_support.rb', line 30

def disable_vpc_classic_link_dns_support(vpc_id)
  response = Excon::Response.new
  unless vpc = self.data[:vpcs].find { |v| v['vpcId'] == vpc_id }
    raise Fog::AWS::Compute::NotFound.new("The VPC '#{vpc_id}' does not exist")
  end
  vpc['classicLinkDnsSupport'] = false
  response.body = {
    'requestId' => Fog::AWS::Mock.request_id,
    'return'    => true
  }
  response
end

#disassociate_address(public_ip, association_id = nil) ⇒ Object



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/fog/aws/requests/compute/disassociate_address.rb', line 32

def disassociate_address(public_ip, association_id=nil)
  response = Excon::Response.new
  response.status = 200
  if address = self.data[:addresses][public_ip]
    if address['allocationId'] && association_id.nil?
      raise Fog::AWS::Compute::Error.new("InvalidParameterValue => You must specify an association id when unmapping an address from a VPC instance")
    end
    instance_id = address['instanceId']
    if instance = self.data[:instances][instance_id]
      instance['ipAddress']         = instance['originalIpAddress']
      instance['dnsName']           = Fog::AWS::Mock.dns_name_for(instance['ipAddress'])
    end
    address['instanceId'] = nil
    response.status = 200
    response.body = {
      'requestId' => Fog::AWS::Mock.request_id,
      'return'    => true
    }
    response
  else
    raise Fog::AWS::Compute::Error.new("AuthFailure => The address '#{public_ip}' does not belong to you.")
  end
end

#disassociate_route_table(association_id) ⇒ Object



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/fog/aws/requests/compute/disassociate_route_table.rb', line 29

def disassociate_route_table(association_id)
  assoc_array = nil
  routetable = self.data[:route_tables].find { |routetable|
    assoc_array = routetable["associationSet"].find { |association|
      association['routeTableAssociationId'].eql? association_id
    }
  }
  if !assoc_array.nil? && assoc_array['main'] == false
    routetable['associationSet'].delete(assoc_array)
    response = Excon::Response.new
    response.status = 200
    response.body = {
        'requestId'     => Fog::AWS::Mock.request_id,
        'return'        => true
    }
    response
  elsif assoc_array.nil?
    raise Fog::AWS::Compute::NotFound.new("The association ID '#{association_id}' does not exist")
  elsif assoc_array['main'] == true
    raise Fog::AWS::Compute::Error, "InvalidParameterValue => cannot disassociate the main route table association #{association_id}"
  end
end

#enable_ec2_classicObject



370
371
372
# File 'lib/fog/aws/compute.rb', line 370

def enable_ec2_classic
  set_supported_platforms(%w[EC2 VPC])
end


30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/fog/aws/requests/compute/enable_vpc_classic_link.rb', line 30

def enable_vpc_classic_link(vpc_id, dry_run=false)
  response = Excon::Response.new
  if vpc = self.data[:vpcs].find{ |v| v['vpcId'] == vpc_id }
    response.status = 200
    response.body = {
      'requestId' => Fog::AWS::Mock.request_id,
      'return'    => true
    }
    vpc['classicLinkEnabled'] = true unless dry_run
    response
  else
    raise Fog::AWS::Compute::NotFound.new("The VPC '#{vpc_id}' does not exist")
  end
end


30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/fog/aws/requests/compute/enable_vpc_classic_link_dns_support.rb', line 30

def enable_vpc_classic_link_dns_support(vpc_id)
  response = Excon::Response.new
  unless vpc = self.data[:vpcs].find { |v| v['vpcId'] == vpc_id }
    raise Fog::AWS::Compute::NotFound.new("The VPC '#{vpc_id}' does not exist")
  end
  vpc['classicLinkDnsSupport'] = true
  response.body = {
    'requestId' => Fog::AWS::Mock.request_id,
    'return'    => true
  }
  response
end

#find_matching_permission_egress(group, permission) ⇒ Object



104
105
106
107
108
109
110
# File 'lib/fog/aws/requests/compute/authorize_security_group_egress.rb', line 104

def find_matching_permission_egress(group, permission)
  group['ipPermissionsEgress'].find do |group_permission|
    permission['ipProtocol'] == group_permission['ipProtocol'] &&
      permission['fromPort'] == group_permission['fromPort'] &&
      permission['toPort'] == group_permission['toPort']
  end
end

#get_console_output(instance_id) ⇒ Object



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/fog/aws/requests/compute/get_console_output.rb', line 32

def get_console_output(instance_id)
  response = Excon::Response.new
  if instance = self.data[:instances][instance_id]
    response.status = 200
    response.body = {
      'instanceId'    => instance_id,
      'output'        => (Time.now - instance['launchTime'] >= Fog::Mock.delay) ? nil : Fog::AWS::Mock.console_output,
      'requestId'     => Fog::AWS::Mock.request_id,
      'timestamp'     => Time.now
    }
    response
  else;
    raise Fog::AWS::Compute::NotFound.new("The instance ID '#{instance_id}' does not exist")
  end
end

#get_password_data(instance_id) ⇒ Object



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/fog/aws/requests/compute/get_password_data.rb', line 34

def get_password_data(instance_id)
  response = Excon::Response.new
  if instance = self.data[:instances][instance_id]
    response.status = 200
    response.body = {
      'instanceId'   => instance_id,
      'passwordData' => nil,
      'requestId'    => Fog::AWS::Mock.request_id,
      'timestamp'    => Time.now
    }
    response
  else;
    raise Fog::AWS::Compute::NotFound.new("The instance ID '#{instance_id}' does not exist")
  end
end

#import_key_pair(key_name, public_key_material) ⇒ Object



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/fog/aws/requests/compute/import_key_pair.rb', line 32

def import_key_pair(key_name, public_key_material)
  response = Excon::Response.new
  unless self.data[:key_pairs][key_name]
    response.status = 200
    data = {
      'keyFingerprint'  => Fog::AWS::Mock.key_fingerprint,
      'keyName'         => key_name
    }
    self.data[:key_pairs][key_name] = data
    response.body = {
      'requestId' => Fog::AWS::Mock.request_id
    }.merge!(data)
    response
  else
    raise Fog::AWS::Compute::Error.new("InvalidKeyPair.Duplicate => The keypair '#{key_name}' already exists.")
  end
end

#modify_image_attribute(image_id, attributes) ⇒ Object

Raises:

  • (ArgumentError)


40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/fog/aws/requests/compute/modify_image_attribute.rb', line 40

def modify_image_attribute(image_id, attributes)
  raise ArgumentError.new("image_id is required") unless image_id

  unless self.data[:images][image_id]
    raise Fog::AWS::Compute::NotFound.new("The AMI ID '#{image_id}' does not exist")
  end

  (attributes['Add.UserId'] || []).each do |user_id|
    if image_launch_permissions = self.data[:image_launch_permissions][image_id]
      image_launch_permissions[:users].push(user_id)
    end
  end

  (attributes['Remove.UserId'] || []).each do |user_id|
    if image_launch_permissions = self.data[:image_launch_permissions][image_id]
      image_launch_permissions[:users].delete(user_id)
    end
  end

  response = Excon::Response.new
  response.status = 200
  response.body = {
    'return'        => true,
    'requestId'     => Fog::AWS::Mock.request_id
  }
  response
end

#modify_network_interface_attribute(network_interface_id, attribute, value) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/fog/aws/requests/compute/modify_network_interface_attribute.rb', line 46

def modify_network_interface_attribute(network_interface_id, attribute, value)
  response = Excon::Response.new
  if self.data[:network_interfaces][network_interface_id]
    nic = self.data[:network_interfaces][network_interface_id]

    case attribute
    when 'description'
      nic['description'] = value.clone
    when 'groupSet'
      groups = {}
      value.each do |group_id|
        security_group = self.data[:security_groups][group_id]
        if security_group.nil?
          raise Fog::AWS::Compute::Error.new("Unknown security group '#{group_id}' specified")
        end
        groups[group_id] = security_group['groupName']
      end
      nic['groupSet'] = groups
    when 'sourceDestCheck'
      nic['sourceDestCheck'] = value
    when 'attachment'
      if nic['attachment'].nil? || value['attachmentId'] != nic['attachment']['attachmentId']
        raise Fog::AWS::Compute::Error.new("Illegal attachment '#{value['attachmentId']}' specified")
      end
      nic['attachment']['deleteOnTermination'] = value['deleteOnTermination']
    else
      raise Fog::AWS::Compute::Error.new("Illegal attribute '#{attribute}' specified")
    end

    response.status = 200
    response.body = {
      'requestId' => Fog::AWS::Mock.request_id,
      'return'    => true
    }

    response
  else
    raise Fog::AWS::Compute::NotFound.new("The network interface '#{network_interface_id}' does not exist")
  end
end

#modify_subnet_attribute(subnet_id, options = {}) ⇒ Object



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/fog/aws/requests/compute/modify_subnet_attribute.rb', line 35

def modify_subnet_attribute(subnet_id, options={})
  Excon::Response.new.tap do |response|
    subnet = self.data[:subnets].detect { |v| v['subnetId'] == subnet_id }            
    if subnet
      subnet['mapPublicIpOnLaunch'] = options['MapPublicIpOnLaunch']

      response.status = 200
      
      response.body = {
        'requestId' => Fog::AWS::Mock.request_id,
        'return'    => true
      }
    else
      response.status = 404
      response.body = {
        'Code' => 'InvalidParameterValue'
      }
    end
  end
end

#modify_volume(volume_id, options = {}) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/fog/aws/requests/compute/modify_volume.rb', line 41

def modify_volume(volume_id, options={})
  response = Excon::Response.new
  volume   = self.data[:volumes][volume_id]

  if volume["volumeType"] == 'standard' && options['VolumeType']
    raise Fog::AWS::Compute::Error.new("InvalidParameterValue => Volume type EBS Magnetic is not supported.")
  end

  volume_modification = {
    'modificationState' => 'modifying',
    'progress'          => 0,
    'startTime'         => Time.now,
    'volumeId'          => volume_id
  }

  if options['Size']
    volume_modification.merge!(
      'originalSize' => volume['size'],
      'targetSize'   => options['Size']
    )
  end

  if options['Iops']
    volume_modification.merge!(
      'originalIops' => volume['iops'],
      'targetIops'   => options['Iops']
    )
  end

  if options['VolumeType']
    if options["VolumeType"] == 'standard'
      raise Fog::AWS::Compute::Error.new("InvalidParameterValue => Volume type EBS Magnetic is not supported.")
    end
    volume_modification.merge!(
      'originalVolumeType' => volume['volumeType'],
      'targetVolumeType'   => options['VolumeType']
    )
  end

  self.data[:volume_modifications][volume_id] = volume_modification

  response.body = {'volumeModification' => volume_modification, 'requestId' => Fog::AWS::Mock.request_id}
  response
end

#modify_volume_attribute(volume_id = nil, auto_enable_io_value = false) ⇒ Object



32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/fog/aws/requests/compute/modify_volume_attribute.rb', line 32

def modify_volume_attribute(volume_id=nil, auto_enable_io_value=false)
  response = Excon::Response.new
  if volume = self.data[:volumes][volume_id]
    response.status = 200
    response.body = {
      'requestId' => Fog::AWS::Mock.request_id,
      'return'    => true
    }
    response
  else
    raise Fog::AWS::Compute::NotFound.new("The volume '#{volume_id}' does not exist.")
  end
end

#modify_vpc_attribute(vpc_id, options = {}) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/fog/aws/requests/compute/modify_vpc_attribute.rb', line 36

def modify_vpc_attribute(vpc_id, options = {})
  response = Excon::Response.new
  if options.size == 0
    raise Fog::AWS::Compute::Error.new("InvalidParameterCombination => No attributes specified.")
  elsif options.size > 1
    raise Fog::AWS::Compute::Error.new("InvalidParameterCombination =>  InvalidParameterCombination => Fields for multiple attribute types specified: #{options.keys.join(', ')}")
  elsif vpc = self.data[:vpcs].find{ |v| v['vpcId'] == vpc_id }
    response.status = 200
    response.body = {
      'requestId' => Fog::AWS::Mock.request_id,
      'return'    => true
    }

    attribute = options.keys.first
    case attribute
    when 'EnableDnsSupport.Value'
      vpc['enableDnsSupport'] = options[attribute]
    when 'EnableDnsHostnames.Value'
      vpc['enableDnsHostnames'] = options[attribute]
    else
      raise Fog::AWS::Compute::Error.new("Illegal attribute '#{attribute}' specified")
    end
    response
  else
    raise Fog::AWS::Compute::NotFound.new("The VPC '#{vpc_id}' does not exist.")
  end
end

#monitor_instances(instance_ids) ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/fog/aws/requests/compute/monitor_instances.rb', line 31

def monitor_instances(instance_ids)
  response        = Excon::Response.new
  response.status = 200
  [*instance_ids].each do |instance_id|
    if instance = self.data[:instances][instance_id]
      instance['monitoring']['state'] = 'enabled'
    else
      raise Fog::AWS::Compute::NotFound.new("The instance ID '#{instance_ids}' does not exist")
    end
  end
  instances_set = [*instance_ids].reduce([]) { |memo, id| memo << {'instanceId' => id, 'monitoring' => 'enabled'} }
  response.body = {'requestId' => 'some_request_id', 'instancesSet' => instances_set}
  response
end

#move_address_to_vpc(public_ip) ⇒ Object



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/fog/aws/requests/compute/move_address_to_vpc.rb', line 27

def move_address_to_vpc(public_ip)
  response      = Excon::Response.new
  allocation_id = "eip-#{Fog::Mock.random_hex(8)}"

  address = self.data[:addresses][public_ip]

  if address
    address['domain']       = 'vpc'
    address['allocationId'] = allocation_id

    response.status = 200
    response.body = {
      'requestId'    => Fog::AWS::Mock.request_id,
      'allocationId' => allocation_id,
      'status'       => "InVpc"
    }

    response
  else
    raise Fog::AWS::Compute::NotFound.new("Address does not exist")
  end
end

#purchase_reserved_instances_offering(reserved_instances_offering_id, instance_count = 1) ⇒ Object



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/fog/aws/requests/compute/purchase_reserved_instances_offering.rb', line 32

def purchase_reserved_instances_offering(reserved_instances_offering_id, instance_count = 1)
  response = Excon::Response.new
  response.status = 200

  # Need to implement filters in the mock to find this there instead of here
  # Also there's no information about what to do when the specified reserved_instances_offering_id doesn't exist
  raise unless reserved_instance_offering = describe_reserved_instances_offerings.body["reservedInstancesOfferingsSet"].find { |offering| offering["reservedInstancesOfferingId"] == reserved_instances_offering_id }

  reserved_instances_id = Fog::AWS::Mock.reserved_instances_id
  reserved_instance_offering.delete('reservedInstancesOfferingId')

  self.data[:reserved_instances][reserved_instances_id] = reserved_instance_offering.merge({
    'reservedInstancesId' => reserved_instances_id,
    'start'               => Time.now,
    'end'                 => Time.now,
    'instanceCount'       => instance_count,
    'state'               => 'payment-pending',
    'tagSet'              => []
  })

  response.body = {
    'reservedInstancesId' => reserved_instances_id,
    'requestId' => Fog::AWS::Mock.request_id
  }

  response
end

#reboot_instances(instance_id = []) ⇒ Object



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/fog/aws/requests/compute/reboot_instances.rb', line 30

def reboot_instances(instance_id = [])
  response = Excon::Response.new
  instance_id = [*instance_id]
  if (self.data[:instances].keys & instance_id).length == instance_id.length
    for instance_id in instance_id
      self.data[:instances][instance_id]['status'] = 'rebooting'
    end
    response.status = 200
    response.body = {
      'requestId' => Fog::AWS::Mock.request_id,
      'return'    => true
    }
    response
  else
    raise Fog::AWS::Compute::NotFound.new("The instance ID #{instance_id.inspect} does not exist")
  end
end

#region_dataObject



338
339
340
# File 'lib/fog/aws/compute.rb', line 338

def region_data
  self.class.data[@region]
end

#register_image(name, description, location, block_devices = [], options = {}) ⇒ Object



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/fog/aws/requests/compute/register_image.rb', line 67

def register_image(name, description, location, block_devices=[], options={})
  unless name.empty?
    image = {
      'imageId' => Fog::AWS::Mock.image_id,
      'imageLocation' => '',
      'imageState' => 'pending',
      'imageOwnerId' => self.data[:owner_id],
      'isPublic' => false,
      'productCodes' => [],
      'architecture' => options['Architecture'] || 'i386',
      'imageType' => 'machine',
      'kernelId' => options['KernelId'] || Fog::AWS::Mock.kernel_id,
      'ramdiskId' => options['RamdiskId'] || Fog::AWS::Mock.ramdisk_id,
      'platform' => 'Linux',
      'stateReason' => {},
      'imageOwnerAlias' => self.data[:owner_id],
      'name' => name,
      'description' => description,
      'rootDeviceType' => '',
      'rootDeviceName' => '',
      'blockDeviceMapping' => [],
      'virtualizationType' => 'paravirtual',
      'hypervisor' => 'xen',
      'registered' => Time.now
    }

    if location[/^\/dev\/(xvd|sd)[a-p]\d{0,2}$/]
      image['rootDeviceName'] = location
      image['rootDeviceType'] = 'ebs'
    else
      image['imageLocation'] = location
    end

    block_devices.each do |bd|
      block_device_mapping = {
        'ebs' => {}
      }
      ["DeviceName","VirtualName"].each do |n|
        block_device_mapping[n] = bd[n] if bd[n]
      end
      ["SnapshotId","VolumeSize","NoDevice","DeleteOnTermination"].each do |n|
        block_device_mapping['ebs'][n] = bd[n] if bd[n]
      end
      image['blockDeviceMapping'] << block_device_mapping
    end

    self.data[:images][image['imageId']] = image

    response = Excon::Response.new
    response.status = 200
    response.body = {
      'requestId' => Fog::AWS::Mock.request_id,
      'imageId' => image['imageId']
    }
    response
  else
    message = 'MissingParameter => '
    if name.empty?
      message << 'The request must contain the parameter name'
    end
    raise Fog::AWS::Compute::Error.new(message)
  end
end

#release_address(public_ip_or_allocation_id) ⇒ Object



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/fog/aws/requests/compute/release_address.rb', line 35

def release_address(public_ip_or_allocation_id)
  response = Excon::Response.new

  address = self.data[:addresses][public_ip_or_allocation_id] || self.data[:addresses].values.find {|a| a['allocationId'] == public_ip_or_allocation_id }

  if address
    if address['allocationId'] && public_ip_or_allocation_id == address['publicIp']
      raise Fog::AWS::Compute::Error, "InvalidParameterValue => You must specify an allocation id when releasing a VPC elastic IP address"
    end

    self.data[:addresses].delete(address['publicIp'])
    response.status = 200
    response.body = {
      'requestId' => Fog::AWS::Mock.request_id,
      'return'    => true
    }
    response
  else
    raise Fog::AWS::Compute::Error.new("AuthFailure => The address '#{public_ip_or_allocation_id}' does not belong to you.")
  end
end

#replace_network_acl_association(association_id, network_acl_id) ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/fog/aws/requests/compute/replace_network_acl_association.rb', line 31

def replace_network_acl_association(association_id, network_acl_id)
  response = Excon::Response.new
  if self.data[:network_acls][network_acl_id]
    # find the old assoc
    old_nacl = self.data[:network_acls].values.find do |n|
      n['associationSet'].find { |assoc| assoc['networkAclAssociationId'] == association_id }
    end

    unless old_nacl
      raise Fog::AWS::Compute::Error.new("Invalid association_id #{association_id}")
    end

    subnet_id = old_nacl['associationSet'].find { |assoc| assoc['networkAclAssociationId'] == association_id }['subnetId']
    old_nacl['associationSet'].delete_if { |assoc| assoc['networkAclAssociationId'] == association_id }

    id = Fog::AWS::Mock.network_acl_association_id
    self.data[:network_acls][network_acl_id]['associationSet'] << {
      'networkAclAssociationId' => id,
      'networkAclId'            => network_acl_id,
      'subnetId'                => subnet_id,
    }

    response.status = 200
    response.body = {
      'requestId'        => Fog::AWS::Mock.request_id,
      'newAssociationId' => id
    }
    response
  else
    raise Fog::AWS::Compute::NotFound.new("The network ACL '#{network_acl_id}' does not exist")
  end
end

#replace_network_acl_entry(network_acl_id, rule_number, protocol, rule_action, cidr_block, egress, options = {}) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/fog/aws/requests/compute/replace_network_acl_entry.rb', line 44

def replace_network_acl_entry(network_acl_id, rule_number, protocol, rule_action, cidr_block, egress, options = {})
  response = Excon::Response.new
  if self.data[:network_acls][network_acl_id]

    unless self.data[:network_acls][network_acl_id]['entrySet'].find { |r| r['ruleNumber'] == rule_number && r['egress'] == egress }
      raise Fog::AWS::Compute::Error.new("No rule with that number")
    end
    self.data[:network_acls][network_acl_id]['entrySet'].delete_if { |r| r['ruleNumber'] == rule_number && r['egress'] == egress }

    data = {
      'ruleNumber'   => rule_number,
      'protocol'     => protocol,
      'ruleAction'   => rule_action,
      'egress'       => egress,
      'cidrBlock'    => cidr_block,
      'icmpTypeCode' => {},
      'portRange'    => {}
    }
    data['icmpTypeCode']['code'] = options['Icmp.Code']      if options['Icmp.Code']
    data['icmpTypeCode']['type'] = options['Icmp.Type']      if options['Icmp.Type']
    data['portRange']['from']    = options['PortRange.From'] if options['PortRange.From']
    data['portRange']['to']      = options['PortRange.To']   if options['PortRange.To']
    self.data[:network_acls][network_acl_id]['entrySet'] << data

    response.status = 200
    response.body = {
      'requestId' => Fog::AWS::Mock.request_id,
      'return'    => true
    }
    response
  else
    raise Fog::AWS::Compute::NotFound.new("The network ACL '#{network_acl_id}' does not exist")
  end
end

#replace_route(route_table_id, destination_cidr_block, options = {}) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/fog/aws/requests/compute/replace_route.rb', line 37

def replace_route(route_table_id, destination_cidr_block, options = {})
  options['instanceOwnerId'] ||= nil
  options['DestinationCidrBlock'] ||= destination_cidr_block

  route_table = self.data[:route_tables].find { |routetable| routetable["routeTableId"].eql? route_table_id }
  if !route_table.nil? && destination_cidr_block
    if !options['gatewayId'].nil? || !options['instanceId'].nil? || !options['networkInterfaceId'].nil?
      if !options['gatewayId'].nil? && self.internet_gateways.all('internet-gateway-id'=>options['gatewayId']).first.nil?
        raise Fog::AWS::Compute::NotFound.new("The gateway ID '#{options['gatewayId']}' does not exist")
      elsif !options['instanceId'].nil? && self.servers.all('instance-id'=>options['instanceId']).first.nil?
        raise Fog::AWS::Compute::NotFound.new("The instance ID '#{options['instanceId']}' does not exist")
      elsif !options['networkInterfaceId'].nil? && self.network_interfaces.all('networkInterfaceId'=>options['networkInterfaceId']).first.nil?
        raise Fog::AWS::Compute::NotFound.new("The networkInterface ID '#{options['networkInterfaceId']}' does not exist")
      elsif route_table['routeSet'].find { |route| route['destinationCidrBlock'].eql? destination_cidr_block }.nil?
        raise Fog::AWS::Compute::Error, "RouteAlreadyExists => The route identified by #{destination_cidr_block} doesn't exist."
      else
        response = Excon::Response.new
        route_set = route_table['routeSet'].find { |routeset| routeset['destinationCidrBlock'].eql? destination_cidr_block }
        route_set.merge!(options)
        route_set['state'] = 'pending'
        route_set['origin'] = 'ReplaceRoute'

        response.status = 200
        response.body = {
          'requestId'=> Fog::AWS::Mock.request_id,
          'return' => true
        }
        response
      end
    else
      message = 'MissingParameter => '
      message << 'The request must contain either a gateway id, a network interface id, or an instance id'
      raise Fog::AWS::Compute::Error.new(message)
    end
  elsif route_table.nil?
    raise Fog::AWS::Compute::NotFound.new("The routeTable ID '#{route_table_id}' does not exist")
  elsif destination_cidr_block.empty?
    raise Fog::AWS::Compute::InvalidParameterValue.new("Value () for parameter destinationCidrBlock is invalid. This is not a valid CIDR block.")
  end
end

#request_spot_instances(image_id, instance_type, spot_price, options = {}) ⇒ Object



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/fog/aws/requests/compute/request_spot_instances.rb', line 96

def request_spot_instances(image_id, instance_type, spot_price, options = {})
  response = Excon::Response.new
  id       = Fog::AWS::Mock.spot_instance_request_id

  if (image_id && instance_type && spot_price)
    response.status = 200

    all_instance_types = flavors.map { |f| f.id }
    if !all_instance_types.include?(instance_type)
      message = "InvalidParameterValue => Invalid value '#{instance_type}' for InstanceType."
      raise Fog::AWS::Compute::Error.new(message)
    end

    spot_price = spot_price.to_f
    if !(spot_price > 0)
      message = "InvalidParameterValue => Value (#{spot_price}) for parameter price is invalid."
      message << " \"#{spot_price}\" is an invalid spot instance price"
      raise Fog::AWS::Compute::Error.new(message)
    end

    if !image_id.match(/^ami-[a-f0-9]{8}$/)
      message = "The image id '[#{image_id}]' does not exist"
      raise Fog::AWS::Compute::NotFound.new(message)
    end

  else
    message = 'MissingParameter => '
    message << 'The request must contain the parameter '
    if !image_id
      message << 'image_id'
    elsif !instance_type
      message << 'instance_type'
    else
      message << 'spot_price'
    end
    raise Fog::AWS::Compute::Error.new(message)
  end

  for key in %w(AvailabilityZoneGroup LaunchGroup)
    if options.is_a?(Hash) && options.key?(key)
      Fog::Logger.warning("#{key} filters are not yet mocked [light_black](#{caller.first})[/]")
      Fog::Mock.not_implemented
    end
  end

  launch_spec = {
    'iamInstanceProfile' => {},
    'blockDeviceMapping' => options['LaunchSpecification.BlockDeviceMapping'] || [],
    'groupSet'           => options['LaunchSpecification.SecurityGroupId']    || ['default'],
    'imageId'            => image_id,
    'instanceType'       => instance_type,
    'monitoring'         => options['LaunchSpecification.Monitoring.Enabled'] || false,
    'subnetId'           => options['LaunchSpecification.SubnetId']           || nil,
    'ebsOptimized'       => options['LaunchSpecification.EbsOptimized']       || false,
    'keyName'            => options['LaunchSpecification.KeyName']            || nil
  }

  if iam_arn = options['LaunchSpecification.IamInstanceProfile.Arn']
    launch_spec['iamInstanceProfile'].merge!('Arn' => iam_arn)
  end

  if iam_name = options['LaunchSpecification.IamInstanceProfile.Name']
    launch_spec['iamInstanceProfile'].merge!('Name' => iam_name)
  end

  spot_request = {
    'launchSpecification'   => launch_spec,
    'spotInstanceRequestId' => id,
    'spotPrice'             => spot_price,
    'type'                  => options['Type'] || 'one-time',
    'state'                 => 'open',
    'fault'                 => {
      'code'    => 'pending-evaluation',
      'message' => 'Your Spot request has been submitted for review, and is pending evaluation.'
    },
    'createTime'         => Time.now,
    'productDescription' => 'Linux/UNIX'
  }

  self.data[:spot_requests][id] = spot_request

  response.body = {
    'spotInstanceRequestSet' => [spot_request],
    'requestId' => Fog::AWS::Mock.request_id
  }

  response
end

#reset_dataObject



346
347
348
# File 'lib/fog/aws/compute.rb', line 346

def reset_data
  self.region_data.delete(@aws_access_key_id)
end

#reset_network_interface_attribute(network_interface_id, attribute) ⇒ Object



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/fog/aws/requests/compute/reset_network_interface_attribute.rb', line 34

def reset_network_interface_attribute(network_interface_id, attribute)
  response = Excon::Response.new
  if self.data[:network_interfaces][network_interface_id]

    response.status = 200
    response.body = {
      'requestId' => Fog::AWS::Mock.request_id,
      'return'    => true
    }
    if attribute == 'sourceDestCheck'
      self.data[:network_interfaces][network_interface_id]['sourceDestCheck'] = true
    else
      raise Fog::AWS::Compute::Error.new("Illegal attribute '#{attribute}' specified")
    end
    response
  else
    raise Fog::AWS::Compute::NotFound.new("The network interface '#{network_interface_id}' does not exist")
  end
end

#restore_address_to_classic(public_ip) ⇒ Object



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/fog/aws/requests/compute/restore_address_to_classic.rb', line 27

def restore_address_to_classic(public_ip)
  response      = Excon::Response.new

  address = self.data[:addresses][public_ip]

  if address
    if address[:origin] == 'vpc'
      raise Fog::AWS::Compute::Error.new("InvalidState => You cannot migrate an Elastic IP address that was originally allocated for use in EC2-VPC to EC2-Classic.")
    end

    address['domain']       = 'standard'
    address.delete("allocationId")

    response.status = 200
    response.body = {
      'requestId' => Fog::AWS::Mock.request_id,
      'publicIp'  => public_ip,
      'status'    => "InClassic"
    }

    response
  else
    raise Fog::AWS::Compute::NotFound.new("Address does not exist")
  end
end

#revoke_security_group_egress(group_name, options = {}) ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/fog/aws/requests/compute/revoke_security_group_egress.rb', line 58

def revoke_security_group_egress(group_name, options = {})
  options = Fog::AWS.parse_security_group_options(group_name, options)

  group = self.data[:security_groups].values.find { |v| v['groupName'] == group_name }

  group ||
    raise(Fog::AWS::Compute::NotFound.new("The security group '#{group_name}' does not exist"))
  response = Excon::Response.new

  verify_permission_options(options, group['vpcId'] != nil)

  normalized_permissions = normalize_permissions(options)

  normalized_permissions.each do |permission|
    if matching_permission = find_matching_permission_egress(group, permission)
      matching_permission['ipRanges'] -= permission['ipRanges']
      matching_permission['groups'] -= permission['groups']

      if matching_permission['ipRanges'].empty? && matching_permission['groups'].empty?
        group['ipPermissionsEgress'].delete(matching_permission)
      end
    end
  end

  response.status = 200
  response.body = {
    'requestId' => Fog::AWS::Mock.request_id,
    'return'    => true
  }
  response
end

#revoke_security_group_ingress(group_name, options = {}) ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/fog/aws/requests/compute/revoke_security_group_ingress.rb', line 58

def revoke_security_group_ingress(group_name, options = {})
  options = Fog::AWS.parse_security_group_options(group_name, options)
  group = self.data[:security_groups].values.find { |v| v['groupName'] == group_name }

  group ||
    raise(Fog::AWS::Compute::NotFound.new("The security group '#{group_name}' does not exist"))
  response = Excon::Response.new

  verify_permission_options(options, group['vpcId'] != nil)

  normalized_permissions = normalize_permissions(options)

  normalized_permissions.each do |permission|
    if matching_permission = find_matching_permission(group, permission)
      matching_permission['ipRanges'] -= permission['ipRanges']
      matching_permission['groups'] -= permission['groups']

      if matching_permission['ipRanges'].empty? && matching_permission['groups'].empty?
        group['ipPermissions'].delete(matching_permission)
      end
    end
  end

  response.status = 200
  response.body = {
    'requestId' => Fog::AWS::Mock.request_id,
    'return'    => true
  }
  response
end

#run_instances(image_id, min_count, max_count, options = {}) ⇒ Object



162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
# File 'lib/fog/aws/requests/compute/run_instances.rb', line 162

def run_instances(image_id, min_count, max_count, options = {})
  response = Excon::Response.new
  response.status = 200

  group_set = [ (options['SecurityGroup'] || 'default') ].flatten
  instances_set = []
  reservation_id = Fog::AWS::Mock.reservation_id

  if options['KeyName'] && describe_key_pairs('key-name' => options['KeyName']).body['keySet'].empty?
    raise Fog::AWS::Compute::NotFound.new("The key pair '#{options['KeyName']}' does not exist")
  end

  min_count.times do |i|
    instance_id = Fog::AWS::Mock.instance_id
    availability_zone = options['Placement.AvailabilityZone'] || Fog::AWS::Mock.availability_zone(@region)

    block_device_mapping = (options['BlockDeviceMapping'] || []).reduce([]) do |mapping, device|
      device_name           = device.fetch("DeviceName", "/dev/sda1")
      volume_size           = device.fetch("Ebs.VolumeSize", 15)            # @todo should pull this from the image
      delete_on_termination = device.fetch("Ebs.DeleteOnTermination", true) # @todo should pull this from the image

      volume_id = create_volume(availability_zone, volume_size).data[:body]["volumeId"]

      self.data[:volumes][volume_id].merge!("DeleteOnTermination" => delete_on_termination)

      mapping << {
        "deviceName"          => device_name,
        "volumeId"            => volume_id,
        "status"              => "attached",
        "attachTime"          => Time.now,
        "deleteOnTermination" => delete_on_termination,
      }
    end

	    hibernation_options = (options['HibernationOptions'] || []).reduce([]) do |mapping, device|
      configure = device.fetch("Configure", true)

      mapping << {
        "Configure" => configure,
      }
    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'] || []).reduce([]) do |mapping, device|
      device_index          = device.fetch("DeviceIndex", 0)
      subnet_id             = device.fetch("SubnetId", options[:subnet_id] ||  Fog::AWS::Mock.subnet_id)
      private_ip_address    = device.fetch("PrivateIpAddress", options[:private_ip_address] || Fog::AWS::Mock.private_ip_address)
      delete_on_termination = device.fetch("DeleteOnTermination", true)
      description           = device.fetch("Description", "mock_network_interface")
      security_group_id     = device.fetch("SecurityGroupId", self.data[:security_groups]['default']['groupId'])
      interface_options     = {
          "PrivateIpAddress"   => private_ip_address,
          "GroupSet"           => device.fetch("GroupSet", [security_group_id]),
          "Description"        => description
      }

      interface_id = device.fetch("NetworkInterfaceId", create_network_interface(subnet_id, interface_options))

      mapping << {
        "networkInterfaceId"  => interface_id,
        "subnetId"            => subnet_id,
        "status"              => "attached",
        "attachTime"          => Time.now,
        "deleteOnTermination" => delete_on_termination,
      }
    end

    instance = {
      'amiLaunchIndex'        => i,
      'associatePublicIP'     => options['associatePublicIP'] || false,
      'architecture'          => 'i386',
      'blockDeviceMapping'    => block_device_mapping,
      'hibernationOptions'    => hibernation_options,
      'networkInterfaces'     => network_interfaces,
      'clientToken'           => options['clientToken'],
      'dnsName'               => nil,
      'ebsOptimized'          => options['EbsOptimized'] || false,
      'hypervisor'            => 'xen',
      'imageId'               => image_id,
      'instanceId'            => instance_id,
      'instanceState'         => { 'code' => 0, 'name' => 'pending' },
      'instanceType'          => options['InstanceType'] || 'm1.small',
      'kernelId'              => options['KernelId'] || Fog::AWS::Mock.kernel_id,
      'keyName'               => options['KeyName'],
      'launchTime'            => Time.now,
      'monitoring'            => { 'state' => options['Monitoring.Enabled'] || false },
      'placement'             => { 'availabilityZone' => availability_zone, 'groupName' => nil, 'tenancy' => options['Placement.Tenancy'] || 'default' },
      'privateDnsName'        => nil,
      'productCodes'          => [],
      'reason'                => nil,
      'rootDeviceName'        => block_device_mapping.first && block_device_mapping.first["deviceName"],
      'rootDeviceType'        => 'instance-store',
      'spotInstanceRequestId' => options['SpotInstanceRequestId'],
      'subnetId'              => options['SubnetId'],
      'virtualizationType'    => 'paravirtual'
    }
    instances_set << instance
    self.data[:instances][instance_id] = instance.merge({
      'groupIds'            => [],
      'groupSet'            => group_set,
      'iamInstanceProfile'  => {},
      'ownerId'             => self.data[:owner_id],
      'reservationId'       => reservation_id,
      'stateReason'         => {}
    })

    if options['SubnetId']
      self.data[:instances][instance_id]['vpcId'] = self.data[:subnets].find{|subnet| subnet['subnetId'] == options['SubnetId'] }['vpcId']

      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,
    'instancesSet'  => instances_set,
    'ownerId'       => self.data[:owner_id],
    'requestId'     => Fog::AWS::Mock.request_id,
    'reservationId' => reservation_id
  }
  response
end

#set_supported_platforms(values) ⇒ Object



378
379
380
# File 'lib/fog/aws/compute.rb', line 378

def set_supported_platforms(values)
  self.data[:account_attributes].find { |h| h["attributeName"] == "supported-platforms" }["values"] = values
end

#setup_credentials(options) ⇒ Object



519
520
521
# File 'lib/fog/aws/compute.rb', line 519

def setup_credentials(options)
  @aws_access_key_id = options[:aws_access_key_id]
end

#setup_default_vpc!Object



391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
# File 'lib/fog/aws/compute.rb', line 391

def setup_default_vpc!
  return if default_vpc.present?

  disable_ec2_classic

  vpc_id = Fog::AWS::Mock.default_vpc_for(region)
  self.default_vpc = vpc_id

  data[:vpcs] << {
    'vpcId' => vpc_id,
    'state' => 'available',
    'cidrBlock' => '172.31.0.0/16',
    'dhcpOptionsId' => Fog::AWS::Mock.dhcp_options_id,
    'tagSet' => {},
    'instanceTenancy' => 'default',
    'enableDnsSupport' => true,
    'enableDnsHostnames' => true,
    'isDefault' => true
  }

  internet_gateway_id = Fog::AWS::Mock.internet_gateway_id
  data[:internet_gateways][internet_gateway_id] = {
    'internetGatewayId' => internet_gateway_id,
    'attachmentSet' => {
      'vpcId' => vpc_id,
      'state' => 'available'
    },
    'tagSet' => {}
  }

  data[:route_tables] << {
    'routeTableId' => Fog::AWS::Mock.route_table_id,
    'vpcId' => vpc_id,
    'routes' => [
      {
        'destinationCidrBlock' => '172.31.0.0/16',
        'gatewayId' => 'local',
        'state' => 'active',
        'origin' => 'CreateRouteTable'
      },
      {
        'destinationCidrBlock' => '0.0.0.0/0',
        'gatewayId' => internet_gateway_id,
        'state' => 'active',
        'origin' => 'CreateRoute'
      }
    ]
  }

  describe_availability_zones.body['availabilityZoneInfo'].map { |z| z['zoneName'] }.each_with_index do |zone, i|
    data[:subnets] << {
      'subnetId'                 => Fog::AWS::Mock.subnet_id,
      'state'                    => 'available',
      'vpcId'                    => vpc_id,
      'cidrBlock'                => "172.31.#{i}.0/16",
      'availableIpAddressCount'  => '251',
      'availabilityZone'         => zone,
      'tagSet'                   => {},
      'mapPublicIpOnLaunch'      => true,
      'defaultForAz'             => true
    }
  end
end

#start_instances(instance_id) ⇒ Object



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/fog/aws/requests/compute/start_instances.rb', line 30

def start_instances(instance_id)
  instance_ids = Array(instance_id)

  instance_set = self.data[:instances].values
  instance_set = apply_tag_filters(instance_set, {'instance_id' => instance_ids}, 'instanceId')
  instance_set = instance_set.select {|x| instance_ids.include?(x["instanceId"]) }

  if instance_set.empty?
    raise Fog::AWS::Compute::NotFound.new("The instance ID '#{instance_ids.first}' does not exist")
  else
    response = Excon::Response.new
    response.status = 200

    response.body = {
      'requestId'    => Fog::AWS::Mock.request_id,
      'instancesSet' => instance_set.reduce([]) do |ia, instance|
                          ia << {'currentState' => { 'code' => 0, 'name' => 'pending' },
                                 'previousState' => instance['instanceState'],
                                 'instanceId' => instance['instanceId'] }
                          instance['instanceState'] = {'code'=>0, 'name'=>'pending'}
                          ia
      end
    }
    response
  end
end

#stop_instances(instance_id, options = {}) ⇒ Object



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/fog/aws/requests/compute/stop_instances.rb', line 39

def stop_instances(instance_id, options = {})
  instance_ids = Array(instance_id)

  instance_set = self.data[:instances].values
  instance_set = apply_tag_filters(instance_set, {'instance_id' => instance_ids}, 'instanceId')
  instance_set = instance_set.select {|x| instance_ids.include?(x["instanceId"]) }

  if instance_set.empty?
    raise Fog::AWS::Compute::NotFound.new("The instance ID '#{instance_ids.first}' does not exist")
  else
    response = Excon::Response.new
    response.status = 200

    response.body = {
      'requestId'    => Fog::AWS::Mock.request_id,
      'instancesSet' => instance_set.reduce([]) do |ia, instance|
                          instance['classicLinkSecurityGroups'] = nil
                          instance['classicLinkVpcId'] = nil
                          ia << {'currentState' => { 'code' => 0, 'name' => 'stopping' },
                                 'previousState' => instance['instanceState'],
                                 'instanceId' => instance['instanceId'] }
                          instance['instanceState'] = {'code'=>0, 'name'=>'stopping'}
                          ia
      end
    }
    response
  end
end

#supported_platformsObject



366
367
368
# File 'lib/fog/aws/compute.rb', line 366

def supported_platforms
  .body["accountAttributeSet"].find{ |h| h["attributeName"] == "supported-platforms" }["values"]
end

#tagged_resources(resources) ⇒ Object



455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
# File 'lib/fog/aws/compute.rb', line 455

def tagged_resources(resources)
  Array(resources).map do |resource_id|
    if match = resource_id.match(/^(\w+)-[a-z0-9]{8,17}/i)
      id = match.captures.first
    else
      raise(Fog::Service::NotFound.new("Unknown resource id #{resource_id}"))
    end

    if MOCKED_TAG_TYPES.has_key? id
      type = MOCKED_TAG_TYPES[id]
    else
      raise(Fog::Service::NotFound.new("Mocking tags of resource #{resource_id} has not been implemented"))
    end

    case type
      when 'image'
        unless visible_images.has_key? resource_id
         raise(Fog::Service::NotFound.new("Cannot tag #{resource_id}, the image does not exist"))
        end
      when 'vpc'
        if self.data[:vpcs].select {|v| v['vpcId'] == resource_id }.empty?
          raise(Fog::Service::NotFound.new("Cannot tag #{resource_id}, the vpc does not exist"))
        end
      when 'route_table'
        unless self.data[:route_tables].detect { |r| r['routeTableId'] == resource_id }
          raise(Fog::Service::NotFound.new("Cannot tag #{resource_id}, the route table does not exist"))
        end
      else
        unless self.data[:"#{type}s"][resource_id]
         raise(Fog::Service::NotFound.new("Cannot tag #{resource_id}, the #{type} does not exist"))
        end
    end
    { 'resourceId' => resource_id, 'resourceType' => type }
  end
end

#terminate_instances(instance_id) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/fog/aws/requests/compute/terminate_instances.rb', line 37

def terminate_instances(instance_id)
  response = Excon::Response.new
  instance_id = [*instance_id]
  if (self.data[:instances].keys & instance_id).length == instance_id.length
    response.body = {
      'requestId'     => Fog::AWS::Mock.request_id,
      'instancesSet'  => []
    }
    response.status = 200
    for id in instance_id
      instance = self.data[:instances][id]
      instance['classicLinkSecurityGroups'] = nil
      instance['classicLinkVpcId'] = nil
      self.data[:deleted_at][id] = Time.now
      code = case instance['instanceState']['name']
      when 'pending'
        0
      when 'running'
        16
      when 'shutting-down'
        32
      when 'terminated'
        48
      when 'stopping'
        64
      when 'stopped'
        80
      end
      state = { 'name' => 'shutting-down', 'code' => 32}
      response.body['instancesSet'] << {
        'instanceId'    => id,
        'previousState' => instance['instanceState'],
        'currentState'  => state
      }
      instance['instanceState'] = state
    end

    describe_addresses.body['addressesSet'].each do |address|
      if instance_id.include?(address['instanceId'])
        disassociate_address(address['publicIp'], address['associationId'])
      end
    end

    describe_volumes.body['volumeSet'].each do |volume|
      if volume['attachmentSet'].first && instance_id.include?(volume['attachmentSet'].first['instanceId'])
        detach_volume(volume['volumeId'])
      end
    end

    response
  else
    raise Fog::AWS::Compute::NotFound.new("The instance ID '#{instance_id}' does not exist")
  end
end

#unmonitor_instances(instance_ids) ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/fog/aws/requests/compute/unmonitor_instances.rb', line 31

def unmonitor_instances(instance_ids)
  response        = Excon::Response.new
  response.status = 200
  [*instance_ids].each do |instance_id|
    if instance = self.data[:instances][instance_id]
      instance['monitoring']['state'] = 'enabled'
    else
      raise Fog::AWS::Compute::NotFound.new("The instance ID '#{instance_ids}' does not exist")
    end
  end
  instances_set = [*instance_ids].reduce([]) { |memo, id| memo << {'instanceId' => id, 'monitoring' => 'disabled'} }
  response.body = {'requestId' => 'some_request_id', 'instancesSet' => instances_set}
  response
end

#visible_imagesObject



350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
# File 'lib/fog/aws/compute.rb', line 350

def visible_images
  images = self.data[:images].values.reduce({}) do |h, image|
    h.update(image['imageId'] => image)
  end

  self.region_data.each do |aws_access_key_id, data|
    data[:image_launch_permissions].each do |image_id, list|
      if list[:users].include?(self.data[:owner_id])
        images.update(image_id => data[:images][image_id])
      end
    end
  end

  images
end