Merge pull request #1452 from rackspace/server_metadata

Rackspace Server/Image metadata operations
This commit is contained in:
Brad Gignac 2013-01-09 13:07:14 -08:00
commit a8d159f375
15 changed files with 500 additions and 6 deletions

View File

@ -104,7 +104,7 @@ module Fog
end
def ignore_attributes(*args)
@ignored_attributes = args
@ignored_attributes = args.collect {|attr| attr.to_s }
end
def ignored_attributes

View File

@ -54,6 +54,13 @@ module Fog
request :get_attachment
request :list_attachments
request :delete_attachment
request :list_metadata
request :set_metadata
request :update_metadata
request :get_metadata_item
request :set_metadata_item
request :delete_metadata_item
class Mock

View File

@ -21,9 +21,30 @@ module Fog
attribute :progress
attribute :minDisk
attribute :minRam
attribute :metadata
attribute :disk_config, :aliases => 'OS-DCF:diskConfig'
attribute :links
ignore_attributes :metadata
def initialize(attributes={})
@connection = attributes[:connection]
super
end
def metadata
raise "Please save image before accessing metadata" unless identity
@metadata ||= begin
Fog::Compute::RackspaceV2::Metadata.new({
:connection => connection,
:parent => self
})
end
end
def metadata=(hash={})
raise "Please save image before accessing metadata" unless identity
metadata.from_hash(hash)
end
def ready?
state == ACTIVE

View File

@ -0,0 +1,33 @@
module Fog
module Compute
class RackspaceV2
module MetaParent
def parent
@parent
end
def parent=(new_parent)
@parent = new_parent
end
def collection_name
if parent.class == Fog::Compute::RackspaceV2::Image
return "images"
elsif parent.class == Fog::Compute::RackspaceV2::Server
return "servers"
else
raise "Metadata is not supported for this model type."
end
end
def metas_to_hash(metas)
hash = {}
metas.each { |meta| hash[meta.key] = meta.value }
hash
end
end
end
end
end

View File

@ -0,0 +1,77 @@
require 'fog/core/collection'
require 'fog/rackspace/models/compute_v2/meta_parent'
require 'fog/rackspace/models/compute_v2/metadatum'
require 'fog/rackspace/models/compute_v2/image'
require 'fog/rackspace/models/compute_v2/server'
module Fog
module Compute
class RackspaceV2
class Metadata < Fog::Collection
model Fog::Compute::RackspaceV2::Metadatum
include Fog::Compute::RackspaceV2::MetaParent
def all
requires :parent
data = connection.list_metadata(collection_name, parent.id).body['metadata']
from_hash(data)
end
def get(key)
requires :parent
data = connection.get_metadata_item(collection_name, parent.id, key).body["meta"]
datum = data.first
new(:key => datum[0], :value => datum[1])
rescue Fog::Compute::RackspaceV2::NotFound
nil
end
def [](key)
return super(key) if key.is_a?(Integer)
return nil unless key
datum = self.find {|datum| datum.key == key || datum.key == key.to_sym }
datum ? datum.value : nil
end
def []=(key, value)
return super(key,value) if key.is_a?(Integer)
return nil unless key
datum = self.find {|datum| datum.key == key || datum.key == key.to_sym }
if datum
data.value = value
else
self << Fog::Compute::RackspaceV2::Metadatum.new(:key => key, :value => value, :connection => connection, :parent => parent)
end
value
end
def save
requires :parent
connection.set_metadata(collection_name, parent.id, to_hash)
end
def new(attributes = {})
requires :parent
super({ :parent => parent }.merge!(attributes))
end
def from_hash(hash)
return unless hash
metas = []
hash.each_pair {|k,v| metas << {:key => k, :value => v} }
load(metas)
end
def to_hash
h = {}
self.each { |datum| h[datum.key] = datum.value }
h
end
end
end
end
end

View File

@ -0,0 +1,29 @@
require 'fog/core/model'
require 'fog/rackspace/models/compute_v2/meta_parent'
module Fog
module Compute
class RackspaceV2
class Metadatum < Fog::Model
include Fog::Compute::RackspaceV2::MetaParent
identity :key
attribute :value
def destroy
requires :identity
connection.delete_metadata_item(collection_name, parent.id, key)
true
end
def save
requires :identity, :value
connection.set_metadata_item(collection_name, parent.id, key, value)
true
end
end
end
end
end

View File

@ -1,4 +1,5 @@
require 'fog/compute/models/server'
require 'fog/rackspace/models/compute_v2/metadata'
module Fog
module Compute
@ -32,7 +33,6 @@ module Fog
attribute :user_id
attribute :tenant_id
attribute :links
attribute :metadata
attribute :personality
attribute :ipv4_address, :aliases => 'accessIPv4'
attribute :ipv6_address, :aliases => 'accessIPv6'
@ -41,8 +41,29 @@ module Fog
attribute :addresses
attribute :flavor_id, :aliases => 'flavor', :squash => 'id'
attribute :image_id, :aliases => 'image', :squash => 'id'
attr_reader :password
ignore_attributes :metadata
attr_reader :password
def initialize(attributes={})
@service = attributes[:service]
super
end
def metadata
raise "Please save server before accessing metadata" unless identity
@metadata ||= begin
Fog::Compute::RackspaceV2::Metadata.new({
:service => service,
:parent => self
})
end
end
def metadata=(hash={})
raise "Please save server before accessing metadata" unless identity
metadata.from_hash(hash)
end
def save
if persisted?
@ -58,7 +79,7 @@ module Fog
options = {}
options[:disk_config] = disk_config unless disk_config.nil?
options[:metadata] = metadata unless metadata.nil?
options[:metadata] = metadata unless @metadata.nil?
options[:personality] = personality unless personality.nil?
data = service.create_server(name, image_id, flavor_id, 1, 1, options)

View File

@ -0,0 +1,26 @@
module Fog
module Compute
class RackspaceV2
class Real
def delete_metadata_item(collection, obj_id, key)
request(
:expects => 204,
:method => 'DELETE',
:path => "/#{collection}/#{obj_id}/metadata/#{key}"
)
end
end
class Mock
def delete_metadata_item(collection, obj_id, key)
raise Fog::Compute::RackspaceV2::NotFound if obj_id == 0
response = Excon::Response.new
response.body = ""
response.status = 204
response
end
end
end
end
end

View File

@ -0,0 +1,26 @@
module Fog
module Compute
class RackspaceV2
class Real
def get_metadata_item(collection, obj_id, key)
request(
:expects => 200,
:method => 'GET',
:path => "/#{collection}/#{obj_id}/metadata/#{key}"
)
end
end
class Mock
def get_metadata_item(collection, obj_id, key)
raise Fog::Compute::RackspaceV2::NotFound if obj_id == 0
response = Excon::Response.new
response.status = 202
response.body = {"meta" => {"environment" => "dev"}}
response
end
end
end
end
end

View File

@ -0,0 +1,26 @@
module Fog
module Compute
class RackspaceV2
class Real
def list_metadata(collection, obj_id)
request(
:expects => [200, 203],
:method => 'GET',
:path => "/#{collection}/#{obj_id}/metadata"
)
end
end
class Mock
def list_metadata(collection, obj_id)
raise Fog::Compute::RackspaceV2::NotFound if obj_id == 0
response = Excon::Response.new
response.status = 202
response.body = { "metadata"=>{"tag"=>"database"} }
response
end
end
end
end
end

View File

@ -0,0 +1,28 @@
module Fog
module Compute
class RackspaceV2
class Real
def set_metadata(collection, obj_id, metadata = {})
request(
:expects => [200, 203],
:method => 'PUT',
:path => "/#{collection}/#{obj_id}/metadata",
:body => Fog::JSON.encode('metadata' => metadata)
)
end
end
class Mock
def set_metadata(collection, obj_id, metadata = {})
raise Fog::Compute::RackspaceV2::NotFound if obj_id == 0
response = Excon::Response.new
response.status = 202
response.body = {"metadata"=>{"environment"=>"dev"}}
response
end
end
end
end
end

View File

@ -0,0 +1,27 @@
module Fog
module Compute
class RackspaceV2
class Real
def set_metadata_item(collection, obj_id, key, value)
request(
:expects => 200,
:method => 'PUT',
:path => "/#{collection}/#{obj_id}/metadata/#{key}",
:body => Fog::JSON.encode('meta' => { key => value })
)
end
end
class Mock
def set_metadata_item(collection, obj_id, key, value)
raise Fog::Compute::RackspaceV2::NotFound if obj_id == 0
response = Excon::Response.new
response.status = 202
response.body = {"meta" => {key => value}}
response
end
end
end
end
end

View File

@ -0,0 +1,27 @@
module Fog
module Compute
class RackspaceV2
class Real
def update_metadata(collection, obj_id, metadata = {})
request(
:expects => [200, 203],
:method => 'POST',
:path => "/#{collection}/#{obj_id}/metadata",
:body => Fog::JSON.encode('metadata' => metadata)
)
end
end
class Mock
def update_metadata(collection, obj_id, metadata = {})
raise Fog::Compute::RackspaceV2::NotFound if obj_id == 0
response = Excon::Response.new
response.status = 202
response.body = {"metadata" => {"environment" => "dev", "tag" => "database"}}
response
end
end
end
end
end

View File

@ -0,0 +1,42 @@
Shindo.tests('Fog::Compute::RackspaceV2 | metadata', ['rackspace']) do
pending if Fog.mocking?
service = Fog::Compute::RackspaceV2.new
test_time = Time.now.to_i.to_s
tests('success') do
begin
@server = service.servers.create(:name => "fog_server_#{test_time}", :flavor_id => 2, :image_id => "3afe97b2-26dc-49c5-a2cc-a2fc8d80c001")
@server.wait_for(timeout=1500) { ready? }
tests('server') do
collection_tests(@server.metadata, {:key => 'my_key', :value => 'my_value'}) do
@server.wait_for { ready? }
end
end
tests('image') do
image_id = @server.create_image("fog_image_#{test_time}", :metadata => {:my_key => 'my_value'})
@image = service.images.get image_id
@image.wait_for(timeout = 1500) { ready? }
tests("#all").succeeds do
pending if Fog.mocking? && !mocks_implemented
metadata = @image.metadata.all
my_metadata = metadata.select {|datum| datum.key == 'my_key'}
returns(1) { my_metadata.size }
returns('my_value') {my_metadata[0].value }
end
tests("#get('my_key')").returns('my_value') do
pending if Fog.mocking? && !mocks_implemented
@image.metadata.get('my_key').value
end
end
ensure
@image.destroy if @image
@server.destroy if @server
end
end
end

View File

@ -0,0 +1,104 @@
Shindo.tests('Fog::Compute::RackspaceV2 | metadata_tests', ['rackspace']) do
@service = Fog::Compute.new(:provider => 'Rackspace', :version => 'V2')
tests('success') do
begin
metadata = {"tag" => "database"}
unless Fog.mocking?
name = "fog-server-metadata-#{Time.now.to_i}"
@server = @service.servers.create(:name => name,
:flavor_id => 2,
:image_id => '3afe97b2-26dc-49c5-a2cc-a2fc8d80c001',
:metadata => metadata)
@server.wait_for(timeout = 1500) { ready? }
@server_id = @server.id
@image_id = @server.create_image(name, :metadata => metadata)
@image = @service.images.get @image_id
else
@image_id = 1
@server_id = 1
end
tests("servers") do
tests('list_metadata').returns("metadata" => metadata) do
@service.list_metadata("servers", @server_id).body
end
tests('set_metadata').returns("metadata" => {"environment" => "dev"}) do
@service.set_metadata("servers", @server_id, {"environment" => "dev"}).body
end
tests('update_metadata').returns("metadata" => {"environment" => "dev", "tag" => "database"}) do
@service.update_metadata("servers", @server_id, {"environment" => "dev", "tag" => "database"}).body
end
tests('get_metadata_item').returns("meta" => {"environment" => "dev"}) do
@service.get_metadata_item("servers", @server_id, "environment").body
end
tests('set_metadata_item').returns("meta" => {"environment" => "test"}) do
@service.set_metadata_item("servers", @server_id, "environment", "test").body
end
tests('delete_metadata_item').succeeds do
@service.delete_metadata_item("servers", @server_id, "environment").body
end
end
tests("images") do
@image.wait_for(timeout = 1500) { ready? } unless Fog.mocking?
tests('list_metadata').returns(metadata) do
h = @service.list_metadata("images", @image_id).body
h["metadata"].reject {|k,v| k.downcase != "tag"} #only look at the metadata we created
end
tests('set_metadata').returns({"environment" => "dev"}) do
h = @service.set_metadata("images", @image_id, {"environment" => "dev"}).body
h["metadata"].reject {|k,v| k.downcase != "environment"} #only look at the metadata we created
end
tests('update_metadata').returns({"environment" => "dev", "tag" => "database"}) do
h = @service.update_metadata("images", @image_id, {"environment" => "dev", "tag" => "database"}).body
h["metadata"].reject {|k,v| !['environment', 'tag'].include?(k.downcase)} #only look at the metadata we created
end
tests('get_metadata_item').returns("meta" => {"environment" => "dev"}) do
@service.get_metadata_item("images", @image_id, "environment").body
end
tests('set_metadata_item').returns("meta" => {"environment" => "test"}) do
@service.set_metadata_item("images", @image_id, "environment", "test").body
end
tests('delete_metadata_item').succeeds do
@service.delete_metadata_item("images", @image_id, "environment").body
end
end
ensure
@image.destroy if @image
@server.destroy if @server
end
end
tests('failure') do
['server', 'image'].each do |collection|
tests(collection) do
tests('list_metadata').raises(Fog::Compute::RackspaceV2::NotFound) do
@service.list_metadata(collection, 0)
end
tests('set_server_metadata').raises(Fog::Compute::RackspaceV2::NotFound) do
@service.set_metadata(collection, 0, {"environment" => "dev"})
end
tests('update_server_metadata').raises(Fog::Compute::RackspaceV2::NotFound) do
@service.update_metadata(collection, 0, {"environment" => "dev", "tag" => "database"})
end
tests('get_server_metadata_item').raises(Fog::Compute::RackspaceV2::NotFound) do
@service.get_metadata_item(collection, 0, "environment")
end
tests('set_server_metadata_item').raises(Fog::Compute::RackspaceV2::NotFound) do
@service.set_metadata_item(collection, 0, "environment", "test")
end
tests('delete_server_metadata_item').raises(Fog::Compute::RackspaceV2::NotFound) do
@service.delete_metadata_item(collection, 0, "environment")
end
end
end
end
end