diff --git a/lib/fog/aws.rb b/lib/fog/aws.rb index a56fda75f..aefe29316 100644 --- a/lib/fog/aws.rb +++ b/lib/fog/aws.rb @@ -22,6 +22,19 @@ module Fog params end + def self.indexed_filters(filters) + params = {} + filters.keys.each_with_index do |key, key_index| + key_index += 1 + params[format('Filter.%d.Name', key_index)] = key + [*filters[key]].each_with_index do |value, value_index| + value_index += 1 + params[format('Filter.%d.Value.%d', key_index, value_index)] = value + end + end + params + end + def self.signed_params(params, options = {}) params.merge!({ 'AWSAccessKeyId' => options[:aws_access_key_id], diff --git a/lib/fog/aws/elb.rb b/lib/fog/aws/elb.rb index 230a39d86..13f5b646b 100644 --- a/lib/fog/aws/elb.rb +++ b/lib/fog/aws/elb.rb @@ -17,7 +17,6 @@ module Fog class Mock def initialize(options={}) - Fog::Mock.not_implemented end end diff --git a/lib/fog/aws/models/compute/addresses.rb b/lib/fog/aws/models/compute/addresses.rb index 1ee69c368..78498769e 100644 --- a/lib/fog/aws/models/compute/addresses.rb +++ b/lib/fog/aws/models/compute/addresses.rb @@ -7,19 +7,19 @@ module Fog class Addresses < Fog::Collection - attribute :public_ip + attribute :filters attribute :server model Fog::AWS::Compute::Address def initialize(attributes) - @public_ip ||= [] + @filters ||= {} super end - def all(public_ip = @public_ip) - @public_ip = public_ip - data = connection.describe_addresses(public_ip).body + def all(filters = @filters) + @filters = filters + data = connection.describe_addresses(filters).body load( data['addressesSet'].map do |address| address.reject {|key, value| value.nil? || value.empty? } @@ -33,10 +33,8 @@ module Fog def get(public_ip) if public_ip - self.class.new(:connection => connection).all(public_ip).first + self.class.new(:connection => connection).all('public-ip' => public_ip).first end - rescue Fog::Errors::NotFound - nil end def new(attributes = {}) diff --git a/lib/fog/aws/models/compute/images.rb b/lib/fog/aws/models/compute/images.rb index d56ba6925..bf7cef4c7 100644 --- a/lib/fog/aws/models/compute/images.rb +++ b/lib/fog/aws/models/compute/images.rb @@ -7,27 +7,25 @@ module Fog class Images < Fog::Collection - attribute :image_id + attribute :filters model Fog::AWS::Compute::Image def initialize(attributes) - @image_id ||= [] + @filters ||= [] super end - def all(image_id = @image_id) - @image_id = image_id - data = connection.describe_images('ImageId' => image_id).body + def all(filters = @filters) + @filters = filters + data = connection.describe_images(@filters).body load(data['imagesSet']) end def get(image_id) if image_id - self.class.new(:connection => connection).all(image_id).first + self.class.new(:connection => connection).all('image-id' => image_id).first end - rescue Fog::Errors::NotFound - nil end end diff --git a/lib/fog/aws/models/compute/key_pairs.rb b/lib/fog/aws/models/compute/key_pairs.rb index dd5d2e652..77ed1d360 100644 --- a/lib/fog/aws/models/compute/key_pairs.rb +++ b/lib/fog/aws/models/compute/key_pairs.rb @@ -12,22 +12,20 @@ module Fog model Fog::AWS::Compute::KeyPair def initialize(attributes) - @key_name ||= [] + @filters ||= {} super end - def all(key_name = @key_name) - @key_name = key_name - data = connection.describe_key_pairs(key_name).body + def all(filters = @filters) + @filters = filters + data = connection.describe_key_pairs(filters).body load(data['keySet']) end def get(key_name) if key_name - self.class.new(:connection => connection).all(key_name).first + self.class.new(:connection => connection).all('key-name' => key_name).first end - rescue Fog::Errors::NotFound - nil end end diff --git a/lib/fog/aws/models/compute/security_groups.rb b/lib/fog/aws/models/compute/security_groups.rb index 7fdd34608..1a4abe87b 100644 --- a/lib/fog/aws/models/compute/security_groups.rb +++ b/lib/fog/aws/models/compute/security_groups.rb @@ -7,27 +7,25 @@ module Fog class SecurityGroups < Fog::Collection - attribute :group_name + attribute :filters model Fog::AWS::Compute::SecurityGroup def initialize(attributes) - @group_name ||= [] + @filters ||= {} super end - def all(group_name = @group_name) - @group_name = group_name - data = connection.describe_security_groups(group_name).body + def all(filters = @filters) + @filters = filters + data = connection.describe_security_groups(@filters).body load(data['securityGroupInfo']) end def get(group_name) if group_name - self.class.new(:connection => connection).all(group_name).first + self.class.new(:connection => connection).all('group-name' => group_name).first end - rescue Fog::Errors::NotFound - nil end end diff --git a/lib/fog/aws/models/compute/server.rb b/lib/fog/aws/models/compute/server.rb index c34af5865..6e0850214 100644 --- a/lib/fog/aws/models/compute/server.rb +++ b/lib/fog/aws/models/compute/server.rb @@ -29,6 +29,7 @@ module Fog attribute :root_device_name, :aliases => 'rootDeviceName' attribute :root_device_type, :aliases => 'rootDeviceType' attribute :state, :aliases => 'instanceState' + attribute :state_reason, :aliases => 'stateReason' attribute :subnet_id, :aliases => 'subnetId' attribute :user_data diff --git a/lib/fog/aws/models/compute/servers.rb b/lib/fog/aws/models/compute/servers.rb index 6a1eca279..926b96bd5 100644 --- a/lib/fog/aws/models/compute/servers.rb +++ b/lib/fog/aws/models/compute/servers.rb @@ -7,18 +7,20 @@ module Fog class Servers < Fog::Collection + attribute :filters + attribute :server_id model Fog::AWS::Compute::Server def initialize(attributes) - @server_id ||= [] + @filters ||= {} super end - def all(server_id = @server_id) - @server_id = server_id - data = connection.describe_instances(server_id).body + def all(filters = @filters) + @filters = filters + data = connection.describe_instances(filters).body load( data['reservationSet'].map do |reservation| reservation['instancesSet'].map do |instance| @@ -60,7 +62,7 @@ module Fog def get(server_id) if server_id - self.class.new(:connection => connection).all(server_id).first + self.class.new(:connection => connection).all('instance-id' => server_id).first end rescue Fog::Errors::NotFound nil diff --git a/lib/fog/aws/models/compute/snapshots.rb b/lib/fog/aws/models/compute/snapshots.rb index 45536753f..0d20a2359 100644 --- a/lib/fog/aws/models/compute/snapshots.rb +++ b/lib/fog/aws/models/compute/snapshots.rb @@ -7,26 +7,22 @@ module Fog class Snapshots < Fog::Collection - attribute :owner, :aliases => 'Owner' - attribute :restorable_by, :aliases => 'RestorableBy' - attribute :snapshot_id + attribute :filters attribute :volume model Fog::AWS::Compute::Snapshot def initialize(attributes) - @snapshot_id ||= [] + @filters ||= { 'RestorableBy' => 'self' } super end - def all(snapshot_id = @snapshot_id, options = {}) - options = { - 'Owner' => @owner || 'self', - 'RestorableBy' => @restorable_by - } - options = options.reject {|key,value| value.nil? || value.to_s.empty?} - merge_attributes(options) - data = connection.describe_snapshots(snapshot_id).body + def all(filters = @filters, options = {}) + unless options.empty? + Formatador.display_line("[yellow][WARN] describe_snapshots with a second param is deprecated, use describe_snapshots(options) instead[/] [light_black](#{caller.first})[/]") + filters.merge!(options) + end + data = connection.describe_snapshots(filters.merge!(options)).body load(data['snapshotSet']) if volume self.replace(self.select {|snapshot| snapshot.volume_id == volume.id}) @@ -36,10 +32,8 @@ module Fog def get(snapshot_id) if snapshot_id - self.class.new(:connection => connection).all(snapshot_id).first + self.class.new(:connection => connection).all('snapshot-id' => snapshot_id).first end - rescue Fog::Errors::NotFound - nil end def new(attributes = {}) diff --git a/lib/fog/aws/models/compute/volumes.rb b/lib/fog/aws/models/compute/volumes.rb index 8587847e5..3d5e1f763 100644 --- a/lib/fog/aws/models/compute/volumes.rb +++ b/lib/fog/aws/models/compute/volumes.rb @@ -7,19 +7,19 @@ module Fog class Volumes < Fog::Collection - attribute :volume_id + attribute :filters attribute :server model Fog::AWS::Compute::Volume def initialize(attributes) - @volume_id ||= [] + @filters ||= {} super end - def all(volume_id = @volume_id) - @volume_id = volume_id - data = connection.describe_volumes(volume_id).body + def all(filters = @filters) + @filters = filters + data = connection.describe_volumes(@filters).body load(data['volumeSet']) if server self.replace(self.select {|volume| volume.server_id == server.id}) @@ -29,10 +29,8 @@ module Fog def get(volume_id) if volume_id - self.class.new(:connection => connection).all(volume_id).first + self.class.new(:connection => connection).all('volume-id' => volume_id).first end - rescue Fog::Errors::NotFound - nil end def new(attributes = {}) diff --git a/lib/fog/aws/parsers/compute/describe_availability_zones.rb b/lib/fog/aws/parsers/compute/describe_availability_zones.rb index 92f27e82d..aef23644a 100644 --- a/lib/fog/aws/parsers/compute/describe_availability_zones.rb +++ b/lib/fog/aws/parsers/compute/describe_availability_zones.rb @@ -6,7 +6,7 @@ module Fog class DescribeAvailabilityZones < Fog::Parsers::Base def reset - @availability_zone = {} + @availability_zone = { 'messageSet' => [] } @response = { 'availabilityZoneInfo' => [] } end @@ -14,7 +14,9 @@ module Fog case name when 'item' @response['availabilityZoneInfo'] << @availability_zone - @availability_zone = {} + @availability_zone = { 'messageSet' => [] } + when 'message' + @availability_zone['messageSet'] << @value when 'regionName', 'zoneName', 'zoneState' @availability_zone[name] = @value when 'requestId' diff --git a/lib/fog/aws/parsers/compute/describe_instances.rb b/lib/fog/aws/parsers/compute/describe_instances.rb index 1f111b9ee..f029cd7dd 100644 --- a/lib/fog/aws/parsers/compute/describe_instances.rb +++ b/lib/fog/aws/parsers/compute/describe_instances.rb @@ -7,7 +7,7 @@ module Fog def reset @block_device_mapping = {} - @instance = { 'blockDeviceMapping' => [], 'instanceState' => {}, 'monitoring' => {}, 'placement' => {}, 'productCodes' => [] } + @instance = { 'blockDeviceMapping' => [], 'instanceState' => {}, 'monitoring' => {}, 'placement' => {}, 'productCodes' => [], 'stateReason' => {} } @reservation = { 'groupSet' => [], 'instancesSet' => [] } @response = { 'reservationSet' => [] } end @@ -21,6 +21,10 @@ module Fog @in_subset = true when 'instancesSet' @in_instances_set = true + when 'instanceState' + @in_instance_state = true + when 'stateReason' + @in_state_reason = true end end @@ -40,7 +44,11 @@ module Fog when 'blockDeviceMapping' @in_block_device_mapping = false when 'code' - @instance['instanceState'][name] = @value.to_i + if @in_instance_state + @instance['instanceState'][name] = @value.to_i + elsif @in_state_reason + @instance['stateReason'][name] = @value.to_i + end when 'deleteOnTermination' if @value == 'true' @block_device_mapping[name] = true @@ -55,13 +63,15 @@ module Fog @in_subset = false when 'instancesSet' @in_instances_set = false + when 'instanceState' + @in_instance_state = false when 'item' if @in_block_device_mapping @instance['blockDeviceMapping'] << @block_device_mapping @block_device_mapping = {} elsif @in_instances_set @reservation['instancesSet'] << @instance - @instance = { 'blockDeviceMapping' => [], 'instanceState' => {}, 'monitoring' => {}, 'placement' => {}, 'productCodes' => [] } + @instance = { 'blockDeviceMapping' => [], 'instanceState' => {}, 'monitoring' => {}, 'placement' => {}, 'productCodes' => [], 'stateReason' => {} } elsif !@in_subset @response['reservationSet'] << @reservation @reservation = { 'groupSet' => [], 'instancesSet' => [] } @@ -69,7 +79,11 @@ module Fog when 'launchTime' @instance[name] = Time.parse(@value) when 'name' - @instance['instanceState'][name] = @value + if @in_instance_state + @instance['instanceState'][name] = @value + elsif @in_state_reason + @instance['stateReason'][name] = @value + end when 'ownerId', 'reservationId' @reservation[name] = @value when 'requestId' @@ -82,6 +96,8 @@ module Fog else @instance['monitoring'][name] = false end + when 'stateReason' + @in_state_reason = false end end diff --git a/lib/fog/aws/parsers/compute/describe_security_groups.rb b/lib/fog/aws/parsers/compute/describe_security_groups.rb index 68c323b21..225fed4c2 100644 --- a/lib/fog/aws/parsers/compute/describe_security_groups.rb +++ b/lib/fog/aws/parsers/compute/describe_security_groups.rb @@ -15,11 +15,12 @@ module Fog def start_element(name, attrs = []) super - if name == 'groups' + case name + when 'groups' @in_groups = true - elsif name == 'ipPermissions' + when 'ipPermissions' @in_ip_permissions = true - elsif name == 'ipRanges' + when 'ipRanges' @in_ip_ranges = true end end diff --git a/lib/fog/aws/parsers/compute/describe_snapshots.rb b/lib/fog/aws/parsers/compute/describe_snapshots.rb index e5e235b8d..20c050445 100644 --- a/lib/fog/aws/parsers/compute/describe_snapshots.rb +++ b/lib/fog/aws/parsers/compute/describe_snapshots.rb @@ -16,7 +16,7 @@ module Fog @response['snapshotSet'] << @snapshot @snapshot = {} when 'description', 'ownerId', 'progress', 'snapshotId', 'status', 'volumeId' - @snapshot[name] = @value + @snapshot[name] ||= @value when 'requestId' @response[name] = @value when 'startTime' diff --git a/lib/fog/aws/requests/compute/describe_addresses.rb b/lib/fog/aws/requests/compute/describe_addresses.rb index 2bc9245d3..2ee51a85c 100644 --- a/lib/fog/aws/requests/compute/describe_addresses.rb +++ b/lib/fog/aws/requests/compute/describe_addresses.rb @@ -8,7 +8,7 @@ module Fog # Describe all or specified IP addresses. # # ==== Parameters - # * public_ip<~Array> - List of ips to describe, defaults to all + # * filters<~Hash> - List of filters to limit results with # # ==== Returns # * response<~Excon::Response>: @@ -17,8 +17,12 @@ module Fog # * 'addressesSet'<~Array>: # * 'instanceId'<~String> - instance for ip address # * 'publicIp'<~String> - ip address for instance - def describe_addresses(public_ip = []) - params = AWS.indexed_param('PublicIp', public_ip) + def describe_addresses(filters = {}) + unless filters.is_a?(Hash) + Formatador.display_line("[yellow][WARN] describe_addresses with #{filters.class} param is deprecated, use describe_addresses('public-ip' => []) instead[/] [light_black](#{caller.first})[/]") + filters = {'public-ip' => [*filters]} + end + params = AWS.indexed_filters(filters) request({ 'Action' => 'DescribeAddresses', :idempotent => true, @@ -30,24 +34,28 @@ module Fog class Mock - def describe_addresses(public_ip = []) + def describe_addresses(filters = {}) + unless filters.is_a?(Hash) + Formatador.display_line("[yellow][WARN] 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 - public_ip = [*public_ip] - if public_ip != [] - addresses_set = @data[:addresses].reject {|key, value| !public_ip.include?(key)}.values - else - addresses_set = @data[:addresses].values - end - if public_ip.length == 0 || public_ip.length == addresses_set.length - response.status = 200 - response.body = { - 'requestId' => Fog::AWS::Mock.request_id, - 'addressesSet' => addresses_set - } - response - else - raise Fog::AWS::Compute::NotFound.new("Address #{public_ip.inspect} not found.") + + addresses_set = @data[:addresses].values + + aliases = {'public-ip' => 'publicIp', 'instance-id' => 'instanceId'} + 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 end diff --git a/lib/fog/aws/requests/compute/describe_availability_zones.rb b/lib/fog/aws/requests/compute/describe_availability_zones.rb index dd1cd8dae..31c646bde 100644 --- a/lib/fog/aws/requests/compute/describe_availability_zones.rb +++ b/lib/fog/aws/requests/compute/describe_availability_zones.rb @@ -8,7 +8,7 @@ module Fog # Describe all or specified availability zones # # ==== Params - # * zone_name<~String> - List of availability zones to describe, defaults to all + # * filters<~Hash> - List of filters to limit results with # # ==== Returns # * response<~Excon::Response>: @@ -18,8 +18,12 @@ module Fog # * 'regionName'<~String> - Name of region # * 'zoneName'<~String> - Name of zone # * 'zoneState'<~String> - State of zone - def describe_availability_zones(zone_name = []) - params = AWS.indexed_param('ZoneName', zone_name) + def describe_availability_zones(filters = {}) + unless filters.is_a?(Hash) + Formatador.display_line("[yellow][WARN] describe_availability_zones with #{filters.class} param is deprecated, use describe_availability_zones('zone-name' => []) instead[/] [light_black](#{caller.first})[/]") + filters = {'public-ip' => [*filters]} + end + params = AWS.indexed_filters(filters) request({ 'Action' => 'DescribeAvailabilityZones', :idempotent => true, @@ -31,31 +35,33 @@ module Fog class Mock - def describe_availability_zones(zone_name = []) - response = Excon::Response.new - zone_name = [*zone_name] - zones = { - 'us-east-1a' => {"zoneName"=>"us-east-1a", "regionName"=>"us-east-1", "zoneState"=>"available"}, - 'us-east-1b' => {"zoneName"=>"us-east-1b", "regionName"=>"us-east-1", "zoneState"=>"available"}, - 'us-east-1c' => {"zoneName"=>"us-east-1c", "regionName"=>"us-east-1", "zoneState"=>"available"}, - 'us-east-1d' => {"zoneName"=>"us-east-1d", "regionName"=>"us-east-1", "zoneState"=>"available"} - } - if zone_name != [] - availability_zone_info = zones.reject {|key, value| !zone_name.include?(key)}.values - else - availability_zone_info = zones.values + def describe_availability_zones(filters = {}) + unless filters.is_a?(Hash) + Formatador.display_line("[yellow][WARN] describe_availability_zones with #{filters.class} param is deprecated, use describe_availability_zones('zone-name' => []) instead[/] [light_black](#{caller.first})[/]") + filters = {'public-ip' => [*filters]} end - if zone_name.length == 0 || zone_name.length == availability_zone_info.length - response.status = 200 - response.body = { - 'requestId' => Fog::AWS::Mock.request_id, - 'availabilityZoneInfo' => availability_zone_info - } - response - else - raise Fog::AWS::Compute::Error.new("InvalidParameterValue => Invalid availability zone: #{zone_name.inspect}") + response = Excon::Response.new + + availability_zone_info = [ + {"regionName"=>"us-east-1", "zoneName"=>"us-east-1a", "zoneState"=>"available"}, + {"regionName"=>"us-east-1", "zoneName"=>"us-east-1b", "zoneState"=>"available"}, + {"regionName"=>"us-east-1", "zoneName"=>"us-east-1c", "zoneState"=>"available"}, + {"regionName"=>"us-east-1", "zoneName"=>"us-east-1d", "zoneState"=>"available"} + ] + + 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 = { + 'requestId' => Fog::AWS::Mock.request_id, + 'availabilityZoneInfo' => availability_zone_info + } + response end end diff --git a/lib/fog/aws/requests/compute/describe_images.rb b/lib/fog/aws/requests/compute/describe_images.rb index 4a47cb9ba..66392064d 100644 --- a/lib/fog/aws/requests/compute/describe_images.rb +++ b/lib/fog/aws/requests/compute/describe_images.rb @@ -8,7 +8,8 @@ module Fog # Describe all or specified images. # # ==== Params - # * options<~Hash> - Optional params + # * filters<~Hash> - List of filters to limit results with + # * filters and/or the following # * 'ExecutableBy'<~String> - Only return images that the executable_by # user has explicit permission to launch # * 'ImageId'<~Array> - Ids of images to describe @@ -33,10 +34,14 @@ module Fog # * 'ramdiskId'<~String> - Ramdisk id associated with image, if any # * 'rootDeviceName'<~String> - Root device name, e.g. /dev/sda1 # * 'rootDeviceType'<~String> - Root device type, ebs or instance-store - def describe_images(options = {}) - if image_id = options.delete('ImageId') - options.merge!(AWS.indexed_param('ImageId', image_id)) + def describe_images(filters = {}) + options = {} + for key in ['ExecutableBy', 'ImageId', 'Owner'] + if filters.key?(key) + options[key] = filters[key] + end end + params = AWS.indexed_filters(filters).merge!(options) request({ 'Action' => 'DescribeImages', :idempotent => true, @@ -48,20 +53,8 @@ module Fog class Mock - def describe_images(options = {}) - response = Excon::Response.new - images = [] - - (rand(101 + 100)).times do - images << Fog::AWS::Mock.image - end - - response.status = 200 - response.body = { - 'requestId' => Fog::AWS::Mock.request_id, - 'imagesSet' => images - } - response + def describe_images(filters = {}) + Fog::Mock.not_implemented end end diff --git a/lib/fog/aws/requests/compute/describe_instances.rb b/lib/fog/aws/requests/compute/describe_instances.rb index 4d48f044d..6702dfcb6 100644 --- a/lib/fog/aws/requests/compute/describe_instances.rb +++ b/lib/fog/aws/requests/compute/describe_instances.rb @@ -8,7 +8,7 @@ module Fog # Describe all or specified instances # # ==== Parameters - # * instance_id<~Array> - List of instance ids to describe, defaults to all + # * filters<~Hash> - List of filters to limit results with # # ==== Returns # * response<~Excon::Response>: @@ -50,8 +50,13 @@ module Fog # * 'rootDeviceType'<~String> - root device type used by AMI in [ebs, instance-store] # * 'ramdiskId'<~String> - Id of ramdisk used to launch instance # * 'reason'<~String> - reason for most recent state transition, or blank - def describe_instances(instance_id = []) - params = AWS.indexed_param('InstanceId', instance_id) + def describe_instances(filters = {}) + unless filters.is_a?(Hash) + Formatador.display_line("[yellow][WARN] describe_instances with #{filters.class} param is deprecated, use describe_instances('instance-id' => []) instead[/] [light_black](#{caller.first})[/]") + filters = {'instance-id' => [*filters]} + end + params = AWS.indexed_filters(filters) + request({ 'Action' => 'DescribeInstances', :idempotent => true, @@ -63,64 +68,126 @@ module Fog class Mock - def describe_instances(instance_id = []) - response = Excon::Response.new - instance_id = [*instance_id] - if instance_id != [] - instance_set = @data[:instances].reject {|key,value| !instance_id.include?(key)}.values - else - instance_set = @data[:instances].values + def describe_instances(filters = {}) + unless filters.is_a?(Hash) + Formatador.display_line("[yellow][WARN] describe_instances with #{filters.class} param is deprecated, use describe_instances('instance-id' => []) instead[/] [light_black](#{caller.first})[/]") + filters = {'instance-id' => [*filters]} end - if instance_id.length == 0 || instance_id.length == instance_set.length - response.status = 200 - reservation_set = {} + response = Excon::Response.new - instance_set.each do |instance| - case instance['instanceState']['name'] - when 'pending' - if Time.now - instance['launchTime'] > Fog::Mock.delay - instance['ipAddress'] = Fog::AWS::Mock.ip_address - instance['dnsName'] = Fog::AWS::Mock.dns_name_for(instance['ipAddress']) - instance['privateIpAddress'] = Fog::AWS::Mock.ip_address - instance['privateDnsName'] = Fog::AWS::Mock.private_dns_name_for(instance['privateIpAddress']) - instance['instanceState'] = { 'code' => 16, 'name' => 'running' } - end - when 'rebooting' - instance['instanceState'] = { 'code' => 16, 'name' => 'running' } - when 'shutting-down' - if Time.now - @data[:deleted_at][instance['instanceId']] > Fog::Mock.delay * 2 - @data[:deleted_at].delete(instance['instanceId']) - @data[:instances].delete(instance['instanceId']) - elsif Time.now - @data[:deleted_at][instance['instanceId']] > Fog::Mock.delay - instance['instanceState'] = { 'code' => 48, 'name' => 'terminating' } - end - when 'terminating' - if Time.now - @data[:deleted_at][instance['instanceId']] > Fog::Mock.delay - @data[:deleted_at].delete(instance['instanceId']) - @data[:instances].delete(instance['instanceId']) - end + instance_set = @data[:instances].values + + aliases = { + 'architecture' => 'architecture', + 'availability-zone' => 'availabilityZone', + 'client-token' => 'clientToken', + 'dns-token' => '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'].detect {|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])} + else + aliased_key = aliases[filter_key] + instance_set = instance_set.reject {|instance| ![*filter_value].include?(instance[aliased_key])} + end + end + + response.status = 200 + reservation_set = {} + + instance_set.each do |instance| + case instance['instanceState']['name'] + when 'pending' + if Time.now - instance['launchTime'] > Fog::Mock.delay + instance['ipAddress'] = Fog::AWS::Mock.ip_address + instance['dnsName'] = Fog::AWS::Mock.dns_name_for(instance['ipAddress']) + instance['privateIpAddress'] = Fog::AWS::Mock.ip_address + instance['privateDnsName'] = Fog::AWS::Mock.private_dns_name_for(instance['privateIpAddress']) + instance['instanceState'] = { 'code' => 16, 'name' => 'running' } end - - if @data[:instances][instance['instanceId']] - reservation_set[instance['reservationId']] ||= { - 'groupSet' => instance['groupSet'], - 'instancesSet' => [], - 'ownerId' => instance['ownerId'], - 'reservationId' => instance['reservationId'] - } - reservation_set[instance['reservationId']]['instancesSet'] << instance.reject{|key,value| !['amiLaunchIndex', 'architecture', 'blockDeviceMapping', 'dnsName', 'imageId', 'instanceId', 'instanceState', 'instanceType', 'ipAddress', 'kernelId', 'keyName', 'launchTime', 'monitoring', 'placement', 'privateDnsName', 'privateIpAddress', 'productCodes', 'ramdiskId', 'reason', 'rootDeviceType'].include?(key)} + when 'rebooting' + instance['instanceState'] = { 'code' => 16, 'name' => 'running' } + when 'shutting-down' + if Time.now - @data[:deleted_at][instance['instanceId']] > Fog::Mock.delay * 2 + @data[:deleted_at].delete(instance['instanceId']) + @data[:instances].delete(instance['instanceId']) + elsif Time.now - @data[:deleted_at][instance['instanceId']] > Fog::Mock.delay + instance['instanceState'] = { 'code' => 48, 'name' => 'terminating' } + end + when 'terminating' + if Time.now - @data[:deleted_at][instance['instanceId']] > Fog::Mock.delay + @data[:deleted_at].delete(instance['instanceId']) + @data[:instances].delete(instance['instanceId']) end end - response.body = { - 'requestId' => Fog::AWS::Mock.request_id, - 'reservationSet' => reservation_set.values - } - response - else - raise Fog::AWS::Compute::NotFound.new("The instance ID #{instance_id.inspect} does not exist") + if @data[:instances][instance['instanceId']] + + reservation_set[instance['reservationId']] ||= { + 'groupSet' => instance['groupSet'], + 'instancesSet' => [], + 'ownerId' => instance['ownerId'], + 'reservationId' => instance['reservationId'] + } + reservation_set[instance['reservationId']]['instancesSet'] << instance.reject{|key,value| !['amiLaunchIndex', 'architecture', 'blockDeviceMapping', 'dnsName', 'imageId', 'instanceId', 'instanceState', 'instanceType', 'ipAddress', 'kernelId', 'keyName', 'launchTime', 'monitoring', 'placement', 'privateDnsName', 'privateIpAddress', 'productCodes', 'ramdiskId', 'reason', 'rootDeviceType'].include?(key)} + end end + + response.body = { + 'requestId' => Fog::AWS::Mock.request_id, + 'reservationSet' => reservation_set.values + } + response end end diff --git a/lib/fog/aws/requests/compute/describe_key_pairs.rb b/lib/fog/aws/requests/compute/describe_key_pairs.rb index 957fc519e..95ab1a4f6 100644 --- a/lib/fog/aws/requests/compute/describe_key_pairs.rb +++ b/lib/fog/aws/requests/compute/describe_key_pairs.rb @@ -8,7 +8,7 @@ module Fog # Describe all or specified key pairs # # ==== Parameters - # * key_name<~Array>:: List of key names to describe, defaults to all + # * filters<~Hash> - List of filters to limit results with # # ==== Returns # * response<~Excon::Response>: @@ -17,8 +17,12 @@ module Fog # * 'keySet'<~Array>: # * 'keyName'<~String> - Name of key # * 'keyFingerprint'<~String> - Fingerprint of key - def describe_key_pairs(key_name = []) - params = AWS.indexed_param('KeyName', key_name) + def describe_key_pairs(filters = {}) + unless filters.is_a?(Hash) + Formatador.display_line("[yellow][WARN] 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 + params = AWS.indexed_filters(filters) request({ 'Action' => 'DescribeKeyPairs', :idempotent => true, @@ -30,26 +34,30 @@ module Fog class Mock - def describe_key_pairs(key_name = []) + def describe_key_pairs(filters = {}) + unless filters.is_a?(Hash) + Formatador.display_line("[yellow][WARN] 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_name = [*key_name] - if key_name != [] - key_set = @data[:key_pairs].reject {|key, value| !key_name.include?(key)}.values - else - key_set = @data[:key_pairs].values - end - if key_name.length == 0 || key_name.length == key_set.length - response.status = 200 - response.body = { - 'requestId' => Fog::AWS::Mock.request_id, - 'keySet' => key_set.map do |key| - key.reject {|key,value| !['keyFingerprint', 'keyName'].include?(key)} - end - } - response - else - raise Fog::AWS::Compute::NotFound.new("The key pair #{key_name.inspect} does not exist") + + key_set = @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| + key.reject {|key,value| !['keyFingerprint', 'keyName'].include?(key)} + end + } + response end end diff --git a/lib/fog/aws/requests/compute/describe_regions.rb b/lib/fog/aws/requests/compute/describe_regions.rb index d2cda7fd1..b096313f8 100644 --- a/lib/fog/aws/requests/compute/describe_regions.rb +++ b/lib/fog/aws/requests/compute/describe_regions.rb @@ -8,7 +8,7 @@ module Fog # Describe all or specified regions # # ==== Params - # * region_name<~String> - List of regions to describe, defaults to all + # * filters<~Hash> - List of filters to limit results with # # ==== Returns # * response<~Excon::Response>: @@ -17,8 +17,12 @@ module Fog # * 'regionInfo'<~Array>: # * 'regionName'<~String> - Name of region # * 'regionEndpoint'<~String> - Service endpoint for region - def describe_regions(region_name = []) - params = AWS.indexed_param('RegionName', region_name) + def describe_regions(filters = {}) + unless filters.is_a?(Hash) + Formatador.display_line("[yellow][WARN] describe_regions with #{filters.class} param is deprecated, use describe_regions('region-name' => []) instead[/] [light_black](#{caller.first})[/]") + filters = {'region-name' => [*filters]} + end + params = AWS.indexed_filters(filters) request({ 'Action' => 'DescribeRegions', :idempotent => true, @@ -30,29 +34,30 @@ module Fog class Mock - def describe_regions(region_name = []) - response = Excon::Response.new - region_name = [*region_name] - regions = { - 'eu-west-1' => {"regionName"=>"eu-west-1", "regionEndpoint"=>"eu-west-1.ec2.amazonaws.com"}, - 'us-east-1' => {"regionName"=>"us-east-1", "regionEndpoint"=>"us-east-1.ec2.amazonaws.com"} - } - if region_name != [] - region_info = regions.reject {|key, value| !region_name.include?(key)}.values - else - region_info = regions.values + def describe_regions(filters = {}) + unless filters.is_a?(Hash) + Formatador.display_line("[yellow][WARN] describe_regions with #{filters.class} param is deprecated, use describe_regions('region-name' => []) instead[/] [light_black](#{caller.first})[/]") + filters = {'region-name' => [*filters]} end - if region_name.length == 0 || region_name.length == region_info.length - response.status = 200 - response.body = { - 'requestId' => Fog::AWS::Mock.request_id, - 'regionInfo' => region_info - } - response - else - raise Fog::AWS::Compute::Error.new("InvalidParameterValue => Invalid region: #{region_name.inspect}") + 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 end diff --git a/lib/fog/aws/requests/compute/describe_reserved_instances.rb b/lib/fog/aws/requests/compute/describe_reserved_instances.rb index 6c2a2591f..0fdd04a1f 100644 --- a/lib/fog/aws/requests/compute/describe_reserved_instances.rb +++ b/lib/fog/aws/requests/compute/describe_reserved_instances.rb @@ -8,7 +8,7 @@ module Fog # Describe all or specified reserved instances # # ==== Parameters - # * reserved_instances_id<~Array> - List of reserved instance ids to describe, defaults to all + # * filters<~Hash> - List of filters to limit results with # # ==== Returns # * response<~Excon::Response>: @@ -25,8 +25,12 @@ module Fog # * 'start'<~Time> - start time for reservation # * 'state'<~String> - state of reserved instance purchase, in .[pending-payment, active, payment-failed, retired] # * 'usagePrice"<~Float> - usage price of reserved instances, per hour - def describe_reserved_instances(reserved_instances_id = []) - params = AWS.indexed_param('ReservedInstancesId', reserved_instances_id) + def describe_reserved_instances(filters = {}) + unless filters.is_a?(Hash) + Formatador.display_line("[yellow][WARN] describe_reserved_instances with #{filters.class} param is deprecated, use describe_reserved_instances('reserved-instances-id' => []) instead[/] [light_black](#{caller.first})[/]") + filters = {'reserved-instances-id' => [*filters]} + end + params = AWS.indexed_filters(filters) request({ 'Action' => 'DescribeReservedInstances', :idempotent => true, @@ -38,7 +42,7 @@ module Fog class Mock - def describe_reserved_instances(reserved_instances_id = {}) + def describe_reserved_instances(filters = {}) Fog::Mock.not_implemented end diff --git a/lib/fog/aws/requests/compute/describe_security_groups.rb b/lib/fog/aws/requests/compute/describe_security_groups.rb index e48594648..977951b8b 100644 --- a/lib/fog/aws/requests/compute/describe_security_groups.rb +++ b/lib/fog/aws/requests/compute/describe_security_groups.rb @@ -8,7 +8,7 @@ module Fog # Describe all or specified security groups # # ==== Parameters - # * group_name<~Array> - List of groups to describe, defaults to all + # * filters<~Hash> - List of filters to limit results with # # === Returns # * response<~Excon::Response>: @@ -27,8 +27,12 @@ module Fog # * 'cidrIp'<~String> - CIDR range # * 'toPort'<~Integer> - End of port range (or -1 for ICMP wildcard) # * 'ownerId'<~String> - AWS Access Key Id of the owner of the security group - def describe_security_groups(group_name = []) - params = AWS.indexed_param('GroupName', group_name) + def describe_security_groups(filters = {}) + unless filters.is_a?(Hash) + Formatador.display_line("[yellow][WARN] 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 + params = AWS.indexed_filters(filters) request({ 'Action' => 'DescribeSecurityGroups', :idempotent => true, @@ -40,24 +44,49 @@ module Fog class Mock - def describe_security_groups(group_name = []) + def describe_security_groups(filters = {}) + unless filters.is_a?(Hash) + Formatador.display_line("[yellow][WARN] 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 - group_name = [*group_name] - if group_name != [] - security_group_info = @data[:security_groups].reject {|key, value| !group_name.include?(key)}.values - else - security_group_info = @data[:security_groups].values - end - if group_name.length == 0 || group_name.length == security_group_info.length - response.status = 200 - response.body = { - 'requestId' => Fog::AWS::Mock.request_id, - 'securityGroupInfo' => security_group_info - } - response - else - raise Fog::AWS::Compute::NotFound.new("The security group #{group_name.inspect} does not exist") + + security_group_info = @data[:security_groups].values + + aliases = { + 'description' => 'groupDescription', + 'group-name' => 'groupName', + 'owner-id' => 'ownerId' + } + permission_aliases = { + 'cidr' => 'cidrIp', + 'from-port' => 'fromPort', + 'protocol' => 'ipProtocol', + 'to-port' => 'toPort' + } + 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{|security_group| !security_group['ipPermissions']['groups'].detect {|group| [*filter_value].include?(group['groupName'])}} + elsif permission_key == 'user-id' + security_group_info = security_group_info.reject{|security_group| !security_group['ipPermissions']['groups'].detect {|group| [*filter_value].include?(group['userId'])}} + else + aliased_key = permission_aliases[filter_key] + security_group_info = security_group_info.reject{|security_group| !security_group['ipPermissions'].detect {|permission| [*filter_value].include?(permission[aliased_key])}} + end + else + aliased_key = aliases[filter_key] + security_group_info = security_group_info.reject{|security_group| ![*filter_value].include?(security_group[aliased_key])} + end end + + response.status = 200 + response.body = { + 'requestId' => Fog::AWS::Mock.request_id, + 'securityGroupInfo' => security_group_info + } + response end end diff --git a/lib/fog/aws/requests/compute/describe_snapshots.rb b/lib/fog/aws/requests/compute/describe_snapshots.rb index da5b11b6b..43f0a9c58 100644 --- a/lib/fog/aws/requests/compute/describe_snapshots.rb +++ b/lib/fog/aws/requests/compute/describe_snapshots.rb @@ -8,8 +8,8 @@ module Fog # Describe all or specified snapshots # # ==== Parameters - # * snapshot_id<~Array> - List of snapshots to describe, defaults to all - # * options<~Array>: + # * filters<~Hash> - List of filters to limit results with + # * options<~Hash>: # * 'Owner'<~String> - Owner of snapshot in ['self', 'amazon', account_id] # * 'RestorableBy'<~String> - Account id of user who can create volumes from this snapshot # @@ -23,55 +23,86 @@ module Fog # * 'startTime'<~Time>: Timestamp of when snapshot was initiated # * 'status'<~String>: Snapshot state, in ['pending', 'completed'] # * 'volumeId'<~String>: Id of volume that snapshot contains - def describe_snapshots(snapshot_id = [], options = {}) - options['Owner'] ||= 'self' - options.merge!(AWS.indexed_param('SnapshotId', snapshot_id)) + def describe_snapshots(filters = {}, options = {}) + unless filters.is_a?(Hash) + Formatador.display_line("[yellow][WARN] 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? + Formatador.display_line("[yellow][WARN] describe_snapshots with a second param is deprecated, use describe_snapshots(options) instead[/] [light_black](#{caller.first})[/]") + end + for key in ['ExecutableBy', 'ImageId', 'Owner', 'RestorableBy'] + if filters.has_key?(key) + options[key] = filters.delete(key) + end + end + options['RestorableBy'] ||= 'self' + params = AWS.indexed_filters(filters).merge!(options) request({ 'Action' => 'DescribeSnapshots', :idempotent => true, :parser => Fog::Parsers::AWS::Compute::DescribeSnapshots.new - }.merge!(options)) + }.merge!(params)) end end class Mock - def describe_snapshots(snapshot_id = []) - response = Excon::Response.new - snapshot_id = [*snapshot_id] - if snapshot_id != [] - snapshot_set = @data[:snapshots].reject {|key,value| !snapshot_id.include?(key)}.values - else - snapshot_set = @data[:snapshots].values + def describe_snapshots(filters = {}, options = {}) + unless filters.is_a?(Hash) + Formatador.display_line("[yellow][WARN] 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? + Formatador.display_line("[yellow][WARN] describe_snapshots with a second param is deprecated, use describe_snapshots(options) instead[/] [light_black](#{caller.first})[/]") end - if snapshot_id.length == 0 || snapshot_id.length == snapshot_set.length - 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 + response = Excon::Response.new + + snapshot_set = @data[:snapshots].values + + if filters.delete('owner-alias') + Formatador.display_line("[yellow][WARN] describe_snapshots with owner-alias is not mocked[/] [light_black](#{caller.first})[/]") + end + + aliases = { + 'description' => 'description', + '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 - - response.status = 200 - response.body = { - 'requestId' => Fog::AWS::Mock.request_id, - 'snapshotSet' => snapshot_set - } - response - else - raise Fog::AWS::Compute::NotFound.new("The snapshot #{snapshot_id.inspect} does not exist.") end + + response.status = 200 + response.body = { + 'requestId' => Fog::AWS::Mock.request_id, + 'snapshotSet' => snapshot_set + } + response end end diff --git a/lib/fog/aws/requests/compute/describe_volumes.rb b/lib/fog/aws/requests/compute/describe_volumes.rb index 9c4b8fa55..ce033c262 100644 --- a/lib/fog/aws/requests/compute/describe_volumes.rb +++ b/lib/fog/aws/requests/compute/describe_volumes.rb @@ -8,7 +8,7 @@ module Fog # Describe all or specified volumes. # # ==== Parameters - # * volume_id<~Array> - List of volumes to describe, defaults to all + # * filters<~Hash> - List of filters to limit results with # # ==== Returns # * response<~Excon::Response>: @@ -26,8 +26,12 @@ module Fog # * 'instanceId'<~String> - Reference to attached instance # * 'status'<~String> - Attachment state # * 'volumeId'<~String> - Reference to volume - def describe_volumes(volume_id = []) - params = AWS.indexed_param('VolumeId', volume_id) + def describe_volumes(filters = {}) + unless filters.is_a?(Hash) + Formatador.display_line("[yellow][WARN] describe_volumes with #{filters.class} param is deprecated, use describe_volumes('volume-id' => []) instead[/] [light_black](#{caller.first})[/]") + filters = {'volume-id' => [*filters]} + end + params = AWS.indexed_filters(filters) request({ 'Action' => 'DescribeVolumes', :idempotent => true, @@ -39,45 +43,67 @@ module Fog class Mock - def describe_volumes(volume_id = []) - response = Excon::Response.new - volume_id = [*volume_id] - if volume_id != [] - volume_set = @data[:volumes].reject {|key,value| !volume_id.include?(key)}.values - else - volume_set = @data[:volumes].values + def describe_volumes(filters = {}) + unless filters.is_a?(Hash) + Formatador.display_line("[yellow][WARN] describe_volumes with #{filters.class} param is deprecated, use describe_volumes('volume-id' => []) instead[/] [light_black](#{caller.first})[/]") + filters = {'volume-id' => [*filters]} end - if volume_id.length == 0 || volume_id.length == volume_set.length - 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 - @data[:deleted_at][volume['volumeId']] > Fog::Mock.delay - @data[:deleted_at].delete(volume['volumeId']) - @data[:volumes].delete(volume['volumeId']) - end + response = Excon::Response.new + + volume_set = @data[:volumes].values + + aliases = { + 'availability-zone' => 'availabilityZone', + 'create-time' => 'createTime', + '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 = permission_aliases[filter_key] + volume_set = volume_set.reject{|volume| !volume['attachmentSet'].detect {|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 - @data[:deleted_at][volume['volumeId']] > Fog::Mock.delay + @data[:deleted_at].delete(volume['volumeId']) + @data[:volumes].delete(volume['volumeId']) end end - - volume_set = volume_set.reject {|volume| !@data[:volumes][volume['volumeId']]} - response.status = 200 - response.body = { - 'requestId' => Fog::AWS::Mock.request_id, - 'volumeSet' => volume_set - } - response - else - raise Fog::AWS::Compute::NotFound.new("The volume #{volume_id.inspect} does not exist.") end + volume_set = volume_set.reject {|volume| !@data[:volumes][volume['volumeId']]} + + response.status = 200 + response.body = { + 'requestId' => Fog::AWS::Mock.request_id, + 'volumeSet' => volume_set + } + response end end diff --git a/tests/aws/requests/compute/address_tests.rb b/tests/aws/requests/compute/address_tests.rb index 566e75575..80df1a69a 100644 --- a/tests/aws/requests/compute/address_tests.rb +++ b/tests/aws/requests/compute/address_tests.rb @@ -26,8 +26,8 @@ Shindo.tests('AWS::Compute | address requests', ['aws']) do AWS[:compute].describe_addresses.body end - tests("#describe_addresses('#{@public_Ip}')").formats(@addresses_format) do - AWS[:compute].describe_addresses(@public_ip).body + tests("#describe_addresses('public-ip' => #{@public_Ip}')").formats(@addresses_format) do + AWS[:compute].describe_addresses('public-ip' => @public_ip).body end tests("#associate_addresses('#{@server.identity}', '#{@public_Ip}')").formats(AWS::Compute::Formats::BASIC) do @@ -47,10 +47,6 @@ Shindo.tests('AWS::Compute | address requests', ['aws']) do @address = AWS[:compute].addresses.create - tests("#describe_addresses('127.0.0.1')").raises(Fog::AWS::Compute::NotFound) do - AWS[:compute].describe_addresses('127.0.0.1') - end - tests("#associate_addresses('i-00000000', '#{@address.identity}')").raises(Fog::AWS::Compute::NotFound) do AWS[:compute].associate_address('i-00000000', @address.identity) end diff --git a/tests/aws/requests/compute/availability_zone_tests.rb b/tests/aws/requests/compute/availability_zone_tests.rb index 6e5b70ef3..494b31a26 100644 --- a/tests/aws/requests/compute/availability_zone_tests.rb +++ b/tests/aws/requests/compute/availability_zone_tests.rb @@ -2,6 +2,7 @@ Shindo.tests('AWS::Compute | availability zone requests', ['aws']) do @availability_zones_format = { 'availabilityZoneInfo' => [{ + 'messageSet' => [], 'regionName' => String, 'zoneName' => String, 'zoneState' => String @@ -15,16 +16,8 @@ Shindo.tests('AWS::Compute | availability zone requests', ['aws']) do AWS[:compute].describe_availability_zones.body end - tests("#describe_availability_zones('us-east-1a')").formats(@availability_zones_format) do - AWS[:compute].describe_availability_zones('us-east-1a').body - end - - end - - tests('failure') do - - tests("#describe_availability_zones('us-east-1e')").raises(Fog::AWS::Compute::Error) do - AWS[:compute].describe_availability_zones('us-east-1e') + tests("#describe_availability_zones('zone-name' => 'us-east-1a')").formats(@availability_zones_format) do + AWS[:compute].describe_availability_zones('zone-name' => 'us-east-1a').body end end diff --git a/tests/aws/requests/compute/image_tests.rb b/tests/aws/requests/compute/image_tests.rb index 6a5d83c01..91531f356 100644 --- a/tests/aws/requests/compute/image_tests.rb +++ b/tests/aws/requests/compute/image_tests.rb @@ -31,11 +31,4 @@ Shindo.tests('AWS::Compute | image requests', ['aws']) do end - tests('failure') do - - tests("#describe_images('ImageId' => 'ami-00000000')").raises(Fog::AWS::Compute::Error) do - AWS[:compute].describe_regions('ImageId' => 'ami-00000000') - end - end - end diff --git a/tests/aws/requests/compute/instance_tests.rb b/tests/aws/requests/compute/instance_tests.rb index e65a7584f..b43ca0ec6 100644 --- a/tests/aws/requests/compute/instance_tests.rb +++ b/tests/aws/requests/compute/instance_tests.rb @@ -21,7 +21,7 @@ Shindo.tests('AWS::Compute | instance requests', ['aws']) do 'ramdiskId' => String, 'reason' => NilClass, # 'rootDeviceName' => String, - 'rootDeviceType' => String + 'rootDeviceType' => String, } @run_instances_format = { @@ -40,7 +40,8 @@ Shindo.tests('AWS::Compute | instance requests', ['aws']) do 'dnsName' => String, 'ipAddress' => String, 'privateDnsName' => String, - 'privateIpAddress' => String + 'privateIpAddress' => String, + 'stateReason' => {} )], 'ownerId' => String, 'reservationId' => String @@ -81,8 +82,8 @@ Shindo.tests('AWS::Compute | instance requests', ['aws']) do # AWS[:compute].describe_instances.body # end - tests("#describe_instances('#{@instance_id}')").formats(@describe_instances_format) do - AWS[:compute].describe_instances(@instance_id).body + tests("#describe_instances('instance-id' => '#{@instance_id}')").formats(@describe_instances_format) do + AWS[:compute].describe_instances('instance-id' => @instance_id).body end tests("#get_console_output('#{@instance_id}')").formats(@get_console_output_format) do @@ -101,10 +102,6 @@ Shindo.tests('AWS::Compute | instance requests', ['aws']) do tests('failure') do - tests("#describe_instances('i-00000000')").raises(Fog::AWS::Compute::NotFound) do - AWS[:compute].describe_instances('i-00000000') - end - tests("#get_console_output('i-00000000')").raises(Fog::AWS::Compute::NotFound) do AWS[:compute].get_console_output('i-00000000') end diff --git a/tests/aws/requests/compute/key_pair_tests.rb b/tests/aws/requests/compute/key_pair_tests.rb index 13db8f0f0..a2e171daa 100644 --- a/tests/aws/requests/compute/key_pair_tests.rb +++ b/tests/aws/requests/compute/key_pair_tests.rb @@ -27,8 +27,8 @@ Shindo.tests('AWS::Compute | key pair requests', ['aws']) do AWS[:compute].describe_key_pairs.body end - tests("#describe_key_pairs(#{@key_pair_name})").formats(@keypairs_format) do - AWS[:compute].describe_key_pairs(@key_pair_name).body + tests("#describe_key_pairs('key-name' => '#{@key_pair_name}')").formats(@keypairs_format) do + AWS[:compute].describe_key_pairs('key-name' => @key_pair_name).body end tests("#delete_key_pair('#{@key_pair_name}')").formats(AWS::Compute::Formats::BASIC) do @@ -56,10 +56,6 @@ Shindo.tests('AWS::Compute | key pair requests', ['aws']) do AWS[:compute].create_key_pair(@key_pair.name) end - tests("#describe_key_pair('not_a_key_name')").raises(Fog::AWS::Compute::NotFound) do - AWS[:compute].describe_key_pairs('not_a_key_name').body - end - @key_pair.destroy end diff --git a/tests/aws/requests/compute/region_tests.rb b/tests/aws/requests/compute/region_tests.rb index 181db0a15..81e5fe6eb 100644 --- a/tests/aws/requests/compute/region_tests.rb +++ b/tests/aws/requests/compute/region_tests.rb @@ -14,17 +14,10 @@ Shindo.tests('AWS::Compute | region requests', ['aws']) do AWS[:compute].describe_regions.body end - tests("#describe_regions('us-east-1')").formats(@regions_format) do - AWS[:compute].describe_regions('us-east-1').body + tests("#describe_regions('region-name' => 'us-east-1')").formats(@regions_format) do + AWS[:compute].describe_regions('region-name' => 'us-east-1').body end end - tests('failure') do - - tests("#describe_regions('us-east-2')").raises(Fog::AWS::Compute::Error) do - AWS[:compute].describe_regions('us-east-2') - end - end - end diff --git a/tests/aws/requests/compute/security_group_tests.rb b/tests/aws/requests/compute/security_group_tests.rb index 36abc343d..c2145b5ca 100644 --- a/tests/aws/requests/compute/security_group_tests.rb +++ b/tests/aws/requests/compute/security_group_tests.rb @@ -16,7 +16,7 @@ Shindo.tests('AWS::Compute | security group requests', ['aws']) do }] } - @owner_id = AWS[:compute].describe_security_groups('default').body['securityGroupInfo'].first['ownerId'] + @owner_id = AWS[:compute].describe_security_groups('group-name' => 'default').body['securityGroupInfo'].first['ownerId'] tests('success') do @@ -45,8 +45,8 @@ Shindo.tests('AWS::Compute | security group requests', ['aws']) do AWS[:compute].describe_security_groups.body end - tests("#describe_security_groups('fog_security_group')").formats(@security_groups_format) do - AWS[:compute].describe_security_groups('fog_security_group').body + tests("#describe_security_groups('group-name' => 'fog_security_group')").formats(@security_groups_format) do + AWS[:compute].describe_security_groups('group-name' => 'fog_security_group').body end tests("#revoke_security_group_ingress({'FromPort' => 80, 'GroupName' => 'fog_security_group', 'IpProtocol' => 'tcp', 'toPort' => 80})").formats(AWS::Compute::Formats::BASIC) do @@ -96,10 +96,6 @@ Shindo.tests('AWS::Compute | security group requests', ['aws']) do }) end - tests("#describe_security_group('not_a_group_name)").raises(Fog::AWS::Compute::NotFound) do - AWS[:compute].describe_security_groups('not_a_group_name') - end - tests("#revoke_security_group_ingress({'FromPort' => 80, 'GroupName' => 'not_a_group_name', 'IpProtocol' => 'tcp', 'toPort' => 80})").raises(Fog::AWS::Compute::NotFound) do AWS[:compute].revoke_security_group_ingress({ 'FromPort' => 80, diff --git a/tests/aws/requests/compute/snapshot_tests.rb b/tests/aws/requests/compute/snapshot_tests.rb index a707ab327..8b7272f15 100644 --- a/tests/aws/requests/compute/snapshot_tests.rb +++ b/tests/aws/requests/compute/snapshot_tests.rb @@ -28,14 +28,15 @@ Shindo.tests('AWS::Compute | snapshot requests', ['aws']) do data end + Fog.wait_for { AWS[:compute].snapshots.get(@snapshot_id) } AWS[:compute].snapshots.get(@snapshot_id).wait_for { ready? } tests("#describe_snapshots").formats(@snapshots_format) do AWS[:compute].describe_snapshots.body end - tests("#describe_snapshots('#{@snapshot_id}')").formats(@snapshots_format) do - AWS[:compute].describe_snapshots(@snapshot_id).body + tests("#describe_snapshots('snapshot-id' => '#{@snapshot_id}')").formats(@snapshots_format) do + AWS[:compute].describe_snapshots('snapshot-id' => @snapshot_id).body end tests("#delete_snapshots(#{@snapshot_id})").formats(AWS::Compute::Formats::BASIC) do @@ -45,10 +46,6 @@ Shindo.tests('AWS::Compute | snapshot requests', ['aws']) do end tests ('failure') do - tests("#describe_snapshot('snap-00000000')").raises(Fog::AWS::Compute::NotFound) do - AWS[:compute].describe_snapshots('snap-00000000') - end - tests("#delete_snapshot('snap-00000000')").raises(Fog::AWS::Compute::NotFound) do AWS[:compute].delete_snapshot('snap-00000000') end diff --git a/tests/aws/requests/compute/volume_tests.rb b/tests/aws/requests/compute/volume_tests.rb index 115990d3f..1d63dc12c 100644 --- a/tests/aws/requests/compute/volume_tests.rb +++ b/tests/aws/requests/compute/volume_tests.rb @@ -51,8 +51,8 @@ Shindo.tests('AWS::Compute | volume requests', ['aws']) do AWS[:compute].describe_volumes.body end - tests("#describe_volumes(#{@volume_id})").formats(@volumes_format) do - AWS[:compute].describe_volumes.body + tests("#describe_volumes('volume-id' => #{@volume_id})").formats(@volumes_format) do + AWS[:compute].describe_volumes('volume-id' => @volume_id).body end tests("#attach_volume(#{@server.identity}, #{@volume_id}, '/dev/sdh')").formats(@volume_attachment_format) do @@ -76,10 +76,6 @@ Shindo.tests('AWS::Compute | volume requests', ['aws']) do @volume = AWS[:compute].volumes.create(:availability_zone => @server.availability_zone, :size => 1) - tests("#describe_volume('vol-00000000')").raises(Fog::AWS::Compute::NotFound) do - AWS[:compute].describe_volumes('vol-00000000') - end - tests("#attach_volume('i-00000000', '#{@volume.identity}', '/dev/sdh')").raises(Fog::AWS::Compute::NotFound) do AWS[:compute].attach_volume('i-00000000', @volume.identity, '/dev/sdh') end