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

Merge pull request #548 from dpiddy/aws-mock-cross-account-image-tagging

[aws|compute] Allow mock tagging to work across accounts.
This commit is contained in:
Dylan Egan 2011-10-07 14:49:42 -07:00
commit 09b2266371
12 changed files with 96 additions and 42 deletions

View file

@ -152,7 +152,10 @@ module Fog
},
:snapshots => {},
:volumes => {},
:tags => {}
:tags => {},
:tag_sets => Hash.new do |tag_set_hash, resource_id|
tag_set_hash[resource_id] = {}
end
}
end
end
@ -172,34 +175,56 @@ module Fog
end
end
def region_data
self.class.data[@region]
end
def data
self.class.data[@region][@aws_access_key_id]
self.region_data[@aws_access_key_id]
end
def reset_data
self.class.data[@region].delete(@aws_access_key_id)
self.region_data.delete(@aws_access_key_id)
end
def apply_tag_filters(resources, filters)
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
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| r['tagSet'].has_key?(value)}
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| r['tagSet'].values.include?(value)}
resources = resources.select{|r| tag_set_fetcher[r].values.include?(value)}
end
# tag:key: match resources taged with a key-value pair. Value may be an array, which is OR'd.
# 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?(r['tagSet'][tag_key])}
resources = resources.select{|r| tag_value.include?(tag_set_fetcher[r][tag_key])}
end
resources

View file

@ -59,7 +59,6 @@ module Fog
response.body = {
'requestId' => Fog::AWS::Mock.request_id
}.merge!(data)
self.data[:snapshots][snapshot_id]['tagSet'] = {}
else
response.status = 400
raise(Excon::Errors.status_error({:expects => 200}, response))

View file

@ -53,7 +53,7 @@ module Fog
when /^vol\-[a-z0-9]{8}$/i
'volume'
end
if type && self.data[:"#{type}s"][resource_id]
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"))
@ -65,7 +65,9 @@ module Fog
self.data[:tags][key][value] ||= []
self.data[:tags][key][value] |= tagged
tagged.each {|resource| self.data[:"#{resource['resourceType']}s"][resource['resourceId']]['tagSet'][key] = value}
tagged.each do |resource|
self.data[:tag_sets][resource['resourceId']][key] = value
end
end
response = Excon::Response.new

View file

@ -60,7 +60,6 @@ module Fog
'size' => size,
'snapshotId' => snapshot_id,
'status' => 'creating',
'tagSet' => {},
'volumeId' => volume_id
}
self.data[:volumes][volume_id] = data

View file

@ -53,7 +53,7 @@ module Fog
when /^vol\-[a-z0-9]{8}$/i
'volume'
end
if type && self.data[:"#{type}s"][resource_id]
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"))
@ -65,9 +65,8 @@ module Fog
end
tagged.each do |resource|
object = self.data[:"#{resource['resourceType']}s"][resource['resourceId']]
tags.each do |key, value|
tagset = object['tagSet']
tagset = self.data[:tag_sets][resource['resourceId']]
tagset.delete(key) if tagset.has_key?(key) && (value.nil? || tagset[key] == value)
end
end

View file

@ -98,24 +98,13 @@ module Fog
'virtualization-type' => 'virtualizationType'
}
image_set = self.data[:images].values
self.class.data[@region].each do |aws_access_key_id, data|
data[:image_launch_permissions].each do |image_id, list|
if list[:users].include?(self.data[:owner_id])
image_set << data[:images][image_id]
end
end
end
image_set = visible_images.values
image_set = apply_tag_filters(image_set, filters, 'imageId')
for filter_key, filter_value in filters
if tag_key = filter_key.split('tag:')[1]
image_set = image_set.reject{|image| ![*filter_value].include?(image['tagSet'][tag_key])}
else
aliased_key = aliases[filter_key]
image_set = image_set.reject{|image| ![*filter_value].include?(image[aliased_key])}
end
end
image_set = image_set.map do |image|
case image['imageState']
@ -124,7 +113,7 @@ module Fog
image['imageState'] = 'available'
end
end
image.reject { |key, value| ['registered'].include?(key) }
image.reject { |key, value| ['registered'].include?(key) }.merge('tagSet' => self.data[:tag_sets][image['imageId']])
end
response.status = 200

View file

@ -88,7 +88,7 @@ module Fog
response = Excon::Response.new
instance_set = self.data[:instances].values
instance_set = apply_tag_filters(instance_set, filters)
instance_set = apply_tag_filters(instance_set, filters, 'instanceId')
aliases = {
'architecture' => 'architecture',
@ -196,7 +196,7 @@ module Fog
'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', 'tagSet'].include?(key)}
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

View file

@ -72,7 +72,7 @@ module Fog
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)
snapshot_set = apply_tag_filters(snapshot_set, filters, 'snapshotId')
aliases = {
'description' => 'description',
@ -106,6 +106,8 @@ module Fog
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,

View file

@ -55,7 +55,7 @@ module Fog
response = Excon::Response.new
volume_set = self.data[:volumes].values
volume_set = apply_tag_filters(volume_set, filters)
volume_set = apply_tag_filters(volume_set, filters, 'volumeId')
aliases = {
'availability-zone' => 'availabilityZone',
@ -102,6 +102,7 @@ module Fog
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 = {

View file

@ -86,7 +86,6 @@ module Fog
'rootDeviceName' => '',
'blockDeviceMapping' => [],
'virtualizationType' => 'paravirtual',
'tagSet' => {},
'hypervisor' => 'xen',
'registered' => Time.now
}

View file

@ -157,8 +157,7 @@ module Fog
'ownerId' => self.data[:owner_id],
'privateIpAddress' => nil,
'reservationId' => reservation_id,
'stateReason' => {},
'tagSet' => {}
'stateReason' => {}
})
end
response.body = {

View file

@ -13,14 +13,54 @@ Shindo.tests('Fog::Compute[:aws] | tag requests', ['aws']) do
@volume.wait_for { ready? }
tests('success') do
if Fog.mocking?
@other_account = Fog::Compute::AWS.new(:aws_access_key_id => 'other', :aws_secret_access_key => 'account')
@image_id = Fog::Compute[:aws].register_image('image', 'image', '/dev/sda1').body['imageId']
end
tests("#create_tags('#{@volume.identity}', 'foo' => 'bar')").formats(AWS::Compute::Formats::BASIC) do
Fog::Compute[:aws].create_tags(@volume.identity, 'foo' => 'bar').body
end
if Fog.mocking?
tests("#create_tags('#{@image_id}', 'foo' => 'baz')").formats(AWS::Compute::Formats::BASIC) do
Fog::Compute[:aws].create_tags(@image_id, 'foo' => 'baz').body
end
end
tests('#describe_tags').formats(@tags_format) do
Fog::Compute[:aws].describe_tags.body
end
expected_identities = Fog.mocking? ? [@volume.identity, @image_id] : [@volume.identity]
tests('#describe_tags').succeeds do
(expected_identities - Fog::Compute[:aws].describe_tags.body['tagSet'].map {|t| t['resourceId'] }).empty?
end
tests("#describe_tags('key' => 'foo', 'value' => 'bar')").returns([@volume.identity]) do
Fog::Compute[:aws].describe_tags('key' => 'foo', 'value' => 'bar').body['tagSet'].map {|t| t['resourceId'] }
end
if Fog.mocking?
tests("#describe_tags('key' => 'foo', 'value' => 'baz')").returns([@image_id]) do
Fog::Compute[:aws].describe_tags('key' => 'foo', 'value' => 'baz').body['tagSet'].map {|t| t['resourceId'] }
end
Fog::Compute[:aws].modify_image_attribute(@image_id, 'Add.UserId' => [@other_account.data[:owner_id]])
tests("other_account#describe_tags('key' => 'foo', 'value' => 'baz')").returns([]) do
@other_account.describe_tags('key' => 'foo', 'value' => 'baz').body['tagSet'].map {|t| t['resourceId'] }
end
tests("other_account#create_tags('#{@image_id}', 'foo' => 'quux')").formats(AWS::Compute::Formats::BASIC) do
@other_account.create_tags(@image_id, 'foo' => 'quux').body
end
tests("other_account#describe_tags('key' => 'foo', 'value' => 'quux')").returns([@image_id]) do
@other_account.describe_tags('key' => 'foo', 'value' => 'quux').body['tagSet'].map {|t| t['resourceId'] }
end
end
tests("#delete_tags('#{@volume.identity}', 'foo' => 'bar')").formats(AWS::Compute::Formats::BASIC) do
Fog::Compute[:aws].delete_tags(@volume.identity, 'foo' => 'bar').body
end