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

[aws|compute] Allow mock tagging to work across accounts.

This moves tag_sets out of individual resources and up to a top-level
item in each mock account's hash. Starting with images, this allows
other mock accounts to create and use their own tags on images they
have launchPermission on.
This commit is contained in:
Dan Peterson 2011-10-06 13:49:28 -07:00
parent 661667eff8
commit 890929ca6b
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

@ -33,13 +33,13 @@ module Fog
end
class Mock
#
# Usage
#
# AWS[:compute].create_snapshot("vol-f7c23423", "latest snapshot")
#
def create_snapshot(volume_id, description = nil)
response = Excon::Response.new
if volume = self.data[:volumes][volume_id]
@ -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"))
@ -64,8 +64,10 @@ module Fog
self.data[:tags][key] ||= {}
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,23 +98,12 @@ 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
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|
@ -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,8 +55,8 @@ 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',
'create-time' => 'createTime',
@ -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