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

Inherits:
Object
  • Object
show all
Defined in:
lib/fog/aws/compute.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/attach_volume.rb,
lib/fog/aws/requests/compute/create_volume.rb,
lib/fog/aws/requests/compute/delete_volume.rb,
lib/fog/aws/requests/compute/describe_tags.rb,
lib/fog/aws/requests/compute/detach_volume.rb,
lib/fog/aws/requests/compute/run_instances.rb,
lib/fog/aws/requests/compute/register_image.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/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_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/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/terminate_instances.rb,
lib/fog/aws/requests/compute/unmonitor_instances.rb,
lib/fog/aws/requests/compute/disassociate_address.rb,
lib/fog/aws/requests/compute/create_security_group.rb,
lib/fog/aws/requests/compute/delete_security_group.rb,
lib/fog/aws/requests/compute/modify_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/describe_availability_zones.rb,
lib/fog/aws/requests/compute/describe_reserved_instances.rb,
lib/fog/aws/requests/compute/revoke_security_group_ingress.rb,
lib/fog/aws/requests/compute/authorize_security_group_ingress.rb,
lib/fog/aws/requests/compute/purchase_reserved_instances_offering.rb,
lib/fog/aws/requests/compute/describe_reserved_instances_offerings.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Mock

Returns a new instance of Mock.



169
170
171
172
173
174
175
176
177
# File 'lib/fog/aws/compute.rb', line 169

def initialize(options={})
  @aws_access_key_id = options[:aws_access_key_id]

  @region = options[:region] || 'us-east-1'

  unless ['ap-northeast-1', 'ap-southeast-1', 'eu-west-1', 'us-east-1', 'us-west-1', 'us-west-2', 'sa-east-1'].include?(@region)
    raise ArgumentError, "Unknown region: #{@region.inspect}"
  end
end

Class Method Details

.dataObject



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
# File 'lib/fog/aws/compute.rb', line 105

def self.data
  @data ||= Hash.new do |hash, region|
    hash[region] = Hash.new do |region_hash, key|
      owner_id = Fog::AWS::Mock.owner_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',
            'ipPermissionsEgress' => [],
            'ipPermissions'       => [
              {
                'groups'      => [{'groupName' => 'default', 'userId' => owner_id}],
                'fromPort'    => -1,
                'toPort'      => -1,
                'ipProtocol'  => 'icmp',
                'ipRanges'    => []
              },
              {
                'groups'      => [{'groupName' => 'default', 'userId' => owner_id}],
                'fromPort'    => 0,
                'toPort'      => 65535,
                'ipProtocol'  => 'tcp',
                'ipRanges'    => []
              },
              {
                'groups'      => [{'groupName' => 'default', 'userId' => owner_id}],
                'fromPort'    => 0,
                'toPort'      => 65535,
                'ipProtocol'  => 'udp',
                'ipRanges'    => []
              }
            ],
            'ownerId'             => owner_id
          }
        },
        :snapshots => {},
        :volumes => {},
        :tags => {},
        :tag_sets => Hash.new do |tag_set_hash, resource_id|
          tag_set_hash[resource_id] = {}
        end
      }
    end
  end
end

.resetObject



165
166
167
# File 'lib/fog/aws/compute.rb', line 165

def self.reset
  @data = nil
end

Instance Method Details

#allocate_address(domain = 'standard') ⇒ 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
# File 'lib/fog/aws/requests/compute/allocate_address.rb', line 32

def allocate_address(domain = 'standard')
  domain = domain == 'vpc' ? 'vpc' : 'standard'
  response = Excon::Response.new
  if describe_addresses.body['addressesSet'].size < self.data[:limits][:addresses]
    response.status = 200
    public_ip = Fog::AWS::Mock.ip_address
    data = {
      'instanceId' => nil,
      'publicIp'   => public_ip,
      'domain'     => domain
    }
    self.data[:addresses][public_ip] = data
    response.body = {
      'domain'    => domain,
      'publicIp'  => public_ip,
      'requestId' => Fog::AWS::Mock.request_id
    }
    response
  else
    response.status = 400
    response.body = "<?xml version=\"1.0\"?><Response><Errors><Error><Code>AddressLimitExceeded</Code><Message>Too many addresses allocated</Message></Error></Errors><RequestID>#{Fog::AWS::Mock.request_id}</RequestID></Response>"
    raise(Excon::Errors.status_error({:expects => 200}, response))
  end
end

#apply_tag_filters(resources, filters, resource_id_key) ⇒ Object



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
# File 'lib/fog/aws/compute.rb', line 207

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.has_key?('tag-key')
    value = filters.delete('tag-key')
    resources = resources.select{|r| tag_set_fetcher[r].has_key?(value)}
  end

  # tag-value: match resources tagged with this value (any key)
  if filters.has_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.include?(tag_set_fetcher[r][tag_key])}
  end

  resources
end

#associate_address(instance_id = nil, public_ip = nil, network_interface_id = nil, allocation_id = nil) ⇒ 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/associate_address.rb', line 43

def associate_address(instance_id=nil, public_ip=nil, network_interface_id=nil, allocation_id=nil)
  public_ip = allocation_id.nil? ? public_ip : nil
  response = Excon::Response.new
  response.status = 200
  instance = self.data[:instances][instance_id]
  address = public_ip.nil? ? nil : self.data[:addresses][public_ip]
  if ((instance && address) || (instance &&  !allocation_id.nil?) || (!allocation_id.nil? && !network_interface_id.nil?))
    if !allocation_id.nil?
      allocation_ip = describe_addresses( 'allocation-id'  => "#{allocation_id}").body['addressesSet']
      public_ip = allocation_ip['publicIp']
    end
    if current_instance = self.data[:instances][address['instanceId']]
      current_instance['ipAddress'] = current_instance['originalIpAddress']
    end
    address['instanceId'] = instance_id
    # detach other address (if any)
    if self.data[:addresses][instance['ipAddress']]
      self.data[:addresses][instance['ipAddress']]['instanceId'] = nil
    end
    instance['ipAddress'] = public_ip
    instance['dnsName'] = Fog::AWS::Mock.dns_name_for(public_ip)
    response.status = 200
    if !instance_id.nil? && !public_ip.nil?
      response.body = {
        'requestId' => Fog::AWS::Mock.request_id,
        'return'    => true
      }
    elsif !allocation_id.nil?
      response.body = {
        'requestId'     => Fog::AWS::Mock.request_id,
        'return'        => true,
        'associationId' => Fog::AWS::Mock.request_id
      }
    end
    response
  #elsif ! network_interface_id.nil? && allocation_id.nil?
  #  raise Fog::Compute::AWS::NotFound.new("You must specify an AllocationId when specifying a NetworkInterfaceID")
  #elsif instance.nil? && network_interface_id.nil?
  #  raise Fog::Compute::AWS::Error.new("You must specify either an InstanceId or a NetworkInterfaceID")
  #elsif !instance && !network_interface_id
  #  raise Fog::Compute::AWS::Error.new(" 2 You must specify either an InstanceId or a NetworkInterfaceID")
  elsif !instance
    raise Fog::Compute::AWS::NotFound.new("You must specify either an InstanceId or a NetworkInterfaceID")
  elsif !address
    raise Fog::Compute::AWS::Error.new("AuthFailure => The address '#{public_ip}' does not belong to you.")
  end
end

#attach_volume(instance_id, volume_id, device) ⇒ 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
# File 'lib/fog/aws/requests/compute/attach_volume.rb', line 41

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::Compute::AWS::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::Compute::AWS::NotFound.new("The instance ID '#{instance_id}' does not exist.")
    elsif !volume
      raise Fog::Compute::AWS::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::Compute::AWS::Error.new(message)
  end
end

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



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
131
132
# File 'lib/fog/aws/requests/compute/authorize_security_group_ingress.rb', line 87

def authorize_security_group_ingress(group_name, options = {})
  if group_name.is_a?(Hash)
    Fog::Logger.deprecation("Fog::AWS::Compute#authorize_security_group_ingress now requires the 'group_name' parameter. Only specifying an options hash is now deprecated [light_black](#{caller.first})[/]")
    options = group_name
    group_name = options.delete('GroupName')
  end

  verify_permission_options(options)

  response = Excon::Response.new
  group = self.data[:security_groups][group_name]

  if group
    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::Compute::AWS::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::Compute::AWS::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
  else
    raise Fog::Compute::AWS::NotFound.new("The security group '#{group_name}' does not exist")
  end
end

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

Usage

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



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/create_image.rb', line 42

def create_image(instance_id, name, description, no_reboot = false)
  response = Excon::Response.new
  if instance_id && !name.empty?
    response.status = 200
    response.body = {
      'requestId' => Fog::AWS::Mock.request_id,
      'imageId' => Fog::AWS::Mock.image_id
    }
  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_key_pair(key_name) ⇒ Object



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

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::Compute::AWS::Error.new("InvalidKeyPair.Duplicate => The keypair '#{key_name}' already exists.")
  end
end

#create_security_group(name, description, vpc_id = nil) ⇒ 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/create_security_group.rb', line 35

def create_security_group(name, description, vpc_id=nil)
  response = Excon::Response.new
  unless self.data[:security_groups][name]
    data = {
      'groupDescription'    => description,
      'groupName'           => name,
      'ipPermissionsEgress' => [],
      'ipPermissions'       => [],
      'ownerId'             => self.data[:owner_id],
      'vpcId'               => vpc_id
    }
    self.data[:security_groups][name] = data
    response.body = {
      'requestId' => Fog::AWS::Mock.request_id,
      'return'    => true
    }
    response
  else
    raise Fog::Compute::AWS::Error.new("InvalidGroup.Duplicate => The security group '#{name}' already exists")
  end
end

#create_snapshot(volume_id, description = nil) ⇒ Object

Usage

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



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
# File 'lib/fog/aws/requests/compute/create_snapshot.rb', line 43

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,
      '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_tags(resources, tags) ⇒ 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
# File 'lib/fog/aws/requests/compute/create_tags.rb', line 43

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

  tagged = resources.map do |resource_id|
    type = case resource_id
    when /^ami\-[a-z0-9]{8}$/i
      'image'
    when /^i\-[a-z0-9]{8}$/i
      'instance'
    when /^snap\-[a-z0-9]{8}$/i
      'snapshot'
    when /^vol\-[a-z0-9]{8}$/i
      'volume'
    end
    if type && ((type == 'image' && visible_images[resource_id]) || self.data[:"#{type}s"][resource_id])
      { 'resourceId' => resource_id, 'resourceType' => type }
    else
      raise(Fog::Service::NotFound.new("The #{type} ID '#{resource_id}' does not exist"))
    end
  end

  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, snapshot_id = nil) ⇒ Object



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
# File 'lib/fog/aws/requests/compute/create_volume.rb', line 40

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

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

    response.status = 200
    volume_id = Fog::AWS::Mock.volume_id
    data = {
      'availabilityZone'  => availability_zone,
      'attachmentSet'     => [],
      'createTime'        => Time.now,
      'size'              => size,
      'snapshotId'        => snapshot_id,
      'status'            => 'creating',
      'volumeId'          => volume_id
    }
    self.data[:volumes][volume_id] = data
    response.body = {
      'requestId' => Fog::AWS::Mock.request_id
    }.merge!(data.reject {|key,value| !['availabilityZone','createTime','size','snapshotId','status','volumeId'].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

#dataObject



183
184
185
# File 'lib/fog/aws/compute.rb', line 183

def data
  self.region_data[@aws_access_key_id]
end

#delete_key_pair(key_name) ⇒ Object



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

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_security_group(name) ⇒ 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
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/fog/aws/requests/compute/delete_security_group.rb', line 32

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

  response = Excon::Response.new
  if self.data[:security_groups][name]

    used_by_groups = []
    self.region_data.each do |access_key, key_data|
      key_data[:security_groups].each do |group_name, group|
        next if group == self.data[:security_groups][name]

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

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

    self.data[:security_groups].delete(name)
    response.status = 200
    response.body = {
      'requestId' => Fog::AWS::Mock.request_id,
      'return'    => true
    }
    response
  else
    raise Fog::Compute::AWS::NotFound.new("The security group '#{name}' does not exist")
  end
end

#delete_snapshot(snapshot_id) ⇒ Object



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

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::Compute::AWS::NotFound.new("The snapshot '#{snapshot_id}' does not exist.")
  end
end

#delete_tags(resources, tags) ⇒ 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
78
79
80
81
# File 'lib/fog/aws/requests/compute/delete_tags.rb', line 44

def delete_tags(resources, tags)
  tagged = Array(resources).map do |resource_id|
    type = case resource_id
    when /^ami\-[a-z0-9]{8}$/i
      'image'
    when /^i\-[a-z0-9]{8}$/i
      'instance'
    when /^snap\-[a-z0-9]{8}$/i
      'snapshot'
    when /^vol\-[a-z0-9]{8}$/i
      'volume'
    end
    if type && ((type == 'image' && visible_images[resource_id]) || self.data[:"#{type}s"][resource_id])
      { 'resourceId' => resource_id, 'resourceType' => type }
    else
      raise(Fog::Service::NotFound.new("The #{type} ID '#{resource_id}' does not exist"))
    end
  end

  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.has_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



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_volume.rb', line 33

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::Compute::AWS::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::Compute::AWS::NotFound.new("The volume '#{volume_id}' does not exist.")
  end
end

#deregister_image(image_id) ⇒ Object



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

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::Compute::AWS::Error.new(message)
  end
end

#describe_addresses(filters = {}) ⇒ Object



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/describe_addresses.rb', line 39

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'}
  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



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
# File 'lib/fog/aws/requests/compute/describe_availability_zones.rb', line 40

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 = {'public-ip' => [*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-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" => "ap-northeast-1", "zoneName" => "ap-northeast-1a", "zoneState" => "available"},
    {"messageSet" => [], "regionName" => "ap-northeast-1", "zoneName" => "ap-northeast-1b", "zoneState" => "available"},

    {"messageSet" => [], "regionName" => "ap-southeast-1", "zoneName" => "ap-southeast-1a", "zoneState" => "available"},
    {"messageSet" => [], "regionName" => "ap-southeast-1", "zoneName" => "ap-southeast-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

#describe_images(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
117
118
119
120
121
122
123
124
125
# File 'lib/fog/aws/requests/compute/describe_images.rb', line 61

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_status(filters = {}) ⇒ Object



21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/fog/aws/requests/compute/describe_instance_status.rb', line 21

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



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
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
# File 'lib/fog/aws/requests/compute/describe_instances.rb', line 82

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'].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

  brand_new_instances = instance_set.find_all 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::Compute::AWS::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['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 - 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']]

      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', 'clientToken', 'dnsName', 'imageId', 'instanceId', 'instanceState', 'instanceType', 'ipAddress', 'kernelId', 'keyName', 'launchTime', 'monitoring', 'placement', 'platform', 'privateDnsName', 'privateIpAddress', 'productCodes', 'ramdiskId', 'reason', 'rootDeviceType', 'stateReason'].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_key_pairs(filters = {}) ⇒ 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
# File 'lib/fog/aws/requests/compute/describe_key_pairs.rb', line 39

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_regions(filters = {}) ⇒ 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
# File 'lib/fog/aws/requests/compute/describe_regions.rb', line 39

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



46
47
48
49
50
51
52
53
54
55
56
# File 'lib/fog/aws/requests/compute/describe_reserved_instances.rb', line 46

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



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_reserved_instances_offerings.rb', line 38

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,
    'usagePrice'          => 0.03,
    'productDescription'  => 'Linux/UNIX',
    'instanceTenancy'     => 'default',
    'currencyCode'         => 'USD'
  }]

  response.body = {
    'reservedInstancesOfferingsSet' => self.data[:reserved_instances_offerings],
    'requestId' => Fog::AWS::Mock.request_id
  }

  response
end

#describe_security_groups(filters = {}) ⇒ Object



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
# File 'lib/fog/aws/requests/compute/describe_security_groups.rb', line 50

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].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'
  }
  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

#describe_snapshots(filters = {}, options = {}) ⇒ 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
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
# File 'lib/fog/aws/requests/compute/describe_snapshots.rb', line 55

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',
    '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_tags(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
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_tags.rb', line 36

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_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
# 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',
    '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'].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 - 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

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



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

def detach_volume(volume_id, options = {})
  response = Excon::Response.new
  response.status = 200
  if (volume = self.data[:volumes][volume_id]) && !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
    raise Fog::Compute::AWS::NotFound.new("The volume '#{volume_id}' does not exist.")
  end
end

#disassociate_address(public_ip) ⇒ Object



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/disassociate_address.rb', line 35

def disassociate_address(public_ip)
  response = Excon::Response.new
  response.status = 200
  if address = self.data[:addresses][public_ip]
    instance_id = address['instanceId']
    instance = self.data[:instances][instance_id]
    instance['ipAddress']         = instance['originalIpAddress']
    instance['dnsName']           = Fog::AWS::Mock.dns_name_for(instance['ipAddress'])
    address['instanceId'] = nil
    response.status = 200
    response.body = {
      'requestId' => Fog::AWS::Mock.request_id,
      'return'    => true
    }
    response
  else
    raise Fog::Compute::AWS::Error.new("AuthFailure => The address '#{public_ip}' does not belong to you.")
  end
end

#get_console_output(instance_id) ⇒ Object



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

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::Compute::AWS::NotFound.new("The instance ID '#{instance_id}' does not exist")
  end
end

#get_password_data(instance_id) ⇒ Object



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

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::Compute::AWS::NotFound.new("The instance ID '#{instance_id}' does not exist")
  end
end

#import_key_pair(key_name, public_key_material) ⇒ Object



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

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::Compute::AWS::Error.new("InvalidKeyPair.Duplicate => The keypair '#{key_name}' already exists.")
  end
end

#modify_image_attribute(image_id, attributes) ⇒ Object

Raises:

  • (ArgumentError)


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/modify_image_attribute.rb', line 43

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::Compute::AWS::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

#monitor_instances(instance_ids) ⇒ Object



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

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::Compute::AWS::NotFound.new("The instance ID '#{instance_ids}' does not exist")
    end
  end
  instances_set = [*instance_ids].inject([]) { |memo, id| memo << {'instanceId' => id, 'monitoring' => 'enabled'} }
  response.body = {'requestId' => 'some_request_id', 'instancesSet' => instances_set}
  response
end

#purchase_reserved_instances_offering(reserved_instances_offering_id, instance_count = 1) ⇒ 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
# File 'lib/fog/aws/requests/compute/purchase_reserved_instances_offering.rb', line 34

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,
    '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



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

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::Compute::AWS::NotFound.new("The instance ID #{instance_id.inspect} does not exist")
  end
end

#region_dataObject



179
180
181
# File 'lib/fog/aws/compute.rb', line 179

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' => 'i386',
      'imageType' => 'machine',
      'kernelId' => Fog::AWS::Mock.kernel_id,
      '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\/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 = 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::Compute::AWS::Error.new(message)
  end
end

#release_address(public_ip) ⇒ Object



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

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

#reset_dataObject



187
188
189
# File 'lib/fog/aws/compute.rb', line 187

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

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



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
# File 'lib/fog/aws/requests/compute/revoke_security_group_ingress.rb', line 64

def revoke_security_group_ingress(group_name, options = {})
  if group_name.is_a?(Hash)
    Fog::Logger.deprecation("Fog::AWS::Compute#revoke_security_group_ingress now requires the 'group_name' parameter. Only specifying an options hash is now deprecated [light_black](#{caller.first})[/]")
    options = group_name
    group_name = options.delete('GroupName')
  end

  verify_permission_options(options)

  response = Excon::Response.new
  group = self.data[:security_groups][group_name]

  if group
    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
  else
    raise Fog::Compute::AWS::NotFound.new("The security group '#{group_name}' does not exist")
  end
end

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



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
# File 'lib/fog/aws/requests/compute/run_instances.rb', line 120

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::Compute::AWS::NotFound.new("The key pair '#{options['KeyName']}' does not exist")
  end

  min_count.times do |i|
    instance_id = Fog::AWS::Mock.instance_id
    instance = {
      'amiLaunchIndex'      => i,
      'blockDeviceMapping'  => [],
      'clientToken'         => options['clientToken'],
      'dnsName'             => nil,
      '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' => options['Placement.AvailabilityZone'] || Fog::AWS::Mock.availability_zone(@region), 'groupName' => nil, 'tenancy' => 'default' },
      'privateDnsName'      => nil,
      'productCodes'        => [],
      'reason'              => nil,
      'rootDeviceType'      => 'instance-store'
    }
    instances_set << instance
    self.data[:instances][instance_id] = instance.merge({
      'architecture'        => 'i386',
      'groupSet'            => group_set,
      'ownerId'             => self.data[:owner_id],
      'privateIpAddress'    => nil,
      'reservationId'       => reservation_id,
      'stateReason'         => {}
    })
  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

#terminate_instances(instance_id) ⇒ Object



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
# File 'lib/fog/aws/requests/compute/terminate_instances.rb', line 40

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]
      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'])
      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::Compute::AWS::NotFound.new("The instance ID '#{instance_id}' does not exist")
  end
end

#unmonitor_instances(instance_ids) ⇒ Object



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

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::Compute::AWS::NotFound.new("The instance ID '#{instance_ids}' does not exist")
    end
  end
  instances_set = [*instance_ids].inject([]) { |memo, id| memo << {'instanceId' => id, 'monitoring' => 'disabled'} }
  response.body = {'requestId' => 'some_request_id', 'instancesSet' => instances_set}
  response
end

#visible_imagesObject



191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
# File 'lib/fog/aws/compute.rb', line 191

def visible_images
  images = self.data[:images].values.inject({}) 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