mirror of
https://github.com/fog/fog.git
synced 2022-11-09 13:51:43 -05:00
Merge pull request #1565 from rackspace/file_metadata
[Rackspace|Storage] Updated File to use the same Metadata class as Directory
This commit is contained in:
commit
3aaa584a88
8 changed files with 195 additions and 125 deletions
|
@ -27,7 +27,7 @@ module Fog
|
|||
end
|
||||
end
|
||||
|
||||
directory.metadata = Metadata.from_headers(data.headers)
|
||||
directory.metadata = Metadata.from_headers(directory, data.headers)
|
||||
directory.files.merge_attributes(options)
|
||||
directory.files.instance_variable_set(:@loaded, true)
|
||||
|
||||
|
|
|
@ -18,19 +18,19 @@ module Fog
|
|||
|
||||
def metadata=(hash)
|
||||
if hash.is_a? Fog::Storage::Rackspace::Metadata
|
||||
@metadata = hash
|
||||
attributes[:metadata] = hash
|
||||
else
|
||||
@metadata = Fog::Storage::Rackspace::Metadata.new(hash)
|
||||
attributes[:metadata] = Fog::Storage::Rackspace::Metadata.new(self, hash)
|
||||
end
|
||||
@metadata
|
||||
attributes[:metadata]
|
||||
end
|
||||
|
||||
def metadata
|
||||
unless @metadata
|
||||
unless attributes[:metadata]
|
||||
response = service.head_container(key)
|
||||
@metadata = Fog::Storage::Rackspace::Metadata.from_headers(response.headers)
|
||||
attributes[:metadata] = Fog::Storage::Rackspace::Metadata.from_headers(self, response.headers)
|
||||
end
|
||||
@metadata
|
||||
attributes[:metadata]
|
||||
end
|
||||
|
||||
def destroy
|
||||
|
@ -81,7 +81,6 @@ module Fog
|
|||
|
||||
def save
|
||||
requires :key
|
||||
|
||||
create_container
|
||||
raise Fog::Storage::Rackspace::Error.new("Directory can not be set as :public without a CDN provided") if public? && !cdn_enabled?
|
||||
@urls = service.cdn.publish_container(self, public?)
|
||||
|
@ -101,7 +100,7 @@ module Fog
|
|||
end
|
||||
|
||||
def create_container
|
||||
headers = @metadata.nil? ? {} : metadata.to_headers
|
||||
headers = attributes[:metadata].nil? ? {} : metadata.to_headers
|
||||
service.put_container(key, headers)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -17,6 +17,9 @@ module Fog
|
|||
|
||||
attr_writer :public
|
||||
|
||||
attr_accessor :directory
|
||||
attr_writer :public
|
||||
|
||||
def body
|
||||
attributes[:body] ||= if last_modified
|
||||
collection.get(identity).body
|
||||
|
@ -29,10 +32,6 @@ module Fog
|
|||
attributes[:body] = new_body
|
||||
end
|
||||
|
||||
def directory
|
||||
@directory
|
||||
end
|
||||
|
||||
def copy(target_directory_key, target_file_key, options={})
|
||||
requires :directory, :key
|
||||
options['Content-Type'] ||= content_type if content_type
|
||||
|
@ -49,10 +48,19 @@ module Fog
|
|||
true
|
||||
end
|
||||
|
||||
def metadata
|
||||
@metadata ||= headers_to_metadata
|
||||
def metadata=(hash)
|
||||
if hash.is_a? Fog::Storage::Rackspace::Metadata
|
||||
attributes[:metadata] = hash
|
||||
else
|
||||
attributes[:metadata] = Fog::Storage::Rackspace::Metadata.new(self, hash)
|
||||
end
|
||||
attributes[:metadata]
|
||||
end
|
||||
|
||||
|
||||
def metadata
|
||||
attributes[:metadata] ||= Fog::Storage::Rackspace::Metadata.new(self)
|
||||
end
|
||||
|
||||
def owner=(new_owner)
|
||||
if new_owner
|
||||
attributes[:owner] = {
|
||||
|
@ -91,71 +99,17 @@ module Fog
|
|||
options['Content-Type'] = content_type if content_type
|
||||
options['Access-Control-Allow-Origin'] = access_control_allow_origin if access_control_allow_origin
|
||||
options['Origin'] = origin if origin
|
||||
options.merge!(metadata_to_headers)
|
||||
options.merge!(metadata.to_headers)
|
||||
|
||||
data = service.put_object(directory.key, key, body, options)
|
||||
update_attributes_from(data)
|
||||
refresh_metadata
|
||||
|
||||
|
||||
self.content_length = Fog::Storage.get_body_size(body)
|
||||
self.content_type ||= Fog::Storage.get_content_type(body)
|
||||
true
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def directory=(new_directory)
|
||||
@directory = new_directory
|
||||
end
|
||||
|
||||
def refresh_metadata
|
||||
metadata.reject! {|k, v| v.nil? }
|
||||
end
|
||||
|
||||
def headers_to_metadata
|
||||
key_map = key_mapping
|
||||
Hash[metadata_attributes.map {|k, v| [key_map[k], v] }]
|
||||
end
|
||||
|
||||
def key_mapping
|
||||
key_map = metadata_attributes
|
||||
key_map.each_pair {|k, v| key_map[k] = header_to_key(k)}
|
||||
end
|
||||
|
||||
def header_to_key(opt)
|
||||
opt.gsub(metadata_prefix, '').split('-').map {|k| k[0, 1].downcase + k[1..-1]}.join('_').to_sym
|
||||
end
|
||||
|
||||
def metadata_to_headers
|
||||
hash = {}
|
||||
metadata.each_pair do |k,v|
|
||||
key = metakey(k,v)
|
||||
hash[key] = v
|
||||
end
|
||||
hash
|
||||
end
|
||||
|
||||
def metakey(key, value)
|
||||
prefix = value.nil? ? "X-Remove-Object-Meta-" : "X-Object-Meta-"
|
||||
prefix + key.to_s.split(/[-_]/).map(&:capitalize).join('-')
|
||||
end
|
||||
|
||||
def metadata_attributes
|
||||
if last_modified
|
||||
headers = service.head_object(directory.key, self.key).headers
|
||||
headers.reject! {|k, v| !metadata_attribute?(k)}
|
||||
else
|
||||
{}
|
||||
end
|
||||
end
|
||||
|
||||
def metadata_attribute?(key)
|
||||
key.to_s =~ /^#{metadata_prefix}/
|
||||
end
|
||||
|
||||
def metadata_prefix
|
||||
"X-Object-Meta-"
|
||||
end
|
||||
private
|
||||
|
||||
def update_attributes_from(data)
|
||||
merge_attributes(data.headers.reject {|key, value| ['Content-Length', 'Content-Type'].include?(key)})
|
||||
|
|
|
@ -55,10 +55,13 @@ module Fog
|
|||
def get(key, &block)
|
||||
requires :directory
|
||||
data = service.get_object(directory.key, key, &block)
|
||||
metadata = Metadata.from_headers(data.headers)
|
||||
file_data = data.headers.merge({
|
||||
:body => data.body,
|
||||
:key => key
|
||||
:key => key,
|
||||
:metadata => metadata
|
||||
})
|
||||
|
||||
new(file_data)
|
||||
rescue Fog::Storage::Rackspace::NotFound
|
||||
nil
|
||||
|
|
|
@ -4,21 +4,24 @@ module Fog
|
|||
|
||||
class Metadata
|
||||
|
||||
# META_PREFIX = "X-Object-Meta-"
|
||||
# REMOVE_META_PREFIX = "X-Remove-Object-Meta-"
|
||||
META_PREFIX = "X-Container-Meta-"
|
||||
REMOVE_META_PREFIX = "X-Remove-Container-Meta-"
|
||||
OBJECT_META_PREFIX = "X-Object-Meta-"
|
||||
OBJECT_REMOVE_META_PREFIX = "X-Remove-Object-Meta-"
|
||||
CONTAINER_META_PREFIX = "X-Container-Meta-"
|
||||
CONTAINER_REMOVE_META_PREFIX = "X-Remove-Container-Meta-"
|
||||
|
||||
# Cloud Files will ignore headers without a value
|
||||
DUMMY_VALUE = 1
|
||||
|
||||
KEY_REGEX = /^#{META_PREFIX}(.*)/
|
||||
CONTAINER_KEY_REGEX = /^#{CONTAINER_META_PREFIX}(.*)/
|
||||
OBJECT_KEY_REGEX = /^#{OBJECT_META_PREFIX}(.*)/
|
||||
|
||||
attr_reader :data
|
||||
|
||||
def initialize(hash={})
|
||||
attr_reader :data, :parent
|
||||
|
||||
def initialize(parent, hash={})
|
||||
@data = hash || {}
|
||||
@deleted_hash = {}
|
||||
@parent = parent
|
||||
end
|
||||
|
||||
def delete(key)
|
||||
|
@ -37,10 +40,10 @@ module Fog
|
|||
headers
|
||||
end
|
||||
|
||||
def self.from_headers(headers)
|
||||
metadata = Metadata.new
|
||||
def self.from_headers(parent, headers)
|
||||
metadata = Metadata.new(parent)
|
||||
headers.each_pair do |k, v|
|
||||
key = Metadata.to_key(k)
|
||||
key = metadata.send(:to_key, k)
|
||||
next unless key
|
||||
metadata.data[key] = v
|
||||
end
|
||||
|
@ -57,8 +60,38 @@ module Fog
|
|||
|
||||
private
|
||||
|
||||
def self.to_key(key)
|
||||
m = key.match KEY_REGEX
|
||||
def meta_prefix
|
||||
if parent.is_a? Fog::Storage::Rackspace::Directory
|
||||
CONTAINER_META_PREFIX
|
||||
elsif parent.is_a? Fog::Storage::Rackspace::File
|
||||
OBJECT_META_PREFIX
|
||||
else
|
||||
raise "Metadata prefix is unknown for #{parent.class}"
|
||||
end
|
||||
end
|
||||
|
||||
def remove_meta_prefix
|
||||
if parent.is_a? Fog::Storage::Rackspace::Directory
|
||||
CONTAINER_REMOVE_META_PREFIX
|
||||
elsif parent.is_a? Fog::Storage::Rackspace::File
|
||||
OBJECT_REMOVE_META_PREFIX
|
||||
else
|
||||
raise "Remove Metadata prefix is unknown for #{parent.class}"
|
||||
end
|
||||
end
|
||||
|
||||
def meta_prefix_regex
|
||||
if parent.is_a? Fog::Storage::Rackspace::Directory
|
||||
CONTAINER_KEY_REGEX
|
||||
elsif parent.is_a? Fog::Storage::Rackspace::File
|
||||
OBJECT_KEY_REGEX
|
||||
else
|
||||
raise "Metadata prefix is unknown for #{parent.class}"
|
||||
end
|
||||
end
|
||||
|
||||
def to_key(key)
|
||||
m = key.match meta_prefix_regex
|
||||
return nil unless m && m[1]
|
||||
|
||||
a = m[1].split('-')
|
||||
|
@ -68,7 +101,7 @@ module Fog
|
|||
end
|
||||
|
||||
def to_header_key(key, value)
|
||||
prefix = value.nil? ? REMOVE_META_PREFIX : META_PREFIX
|
||||
prefix = value.nil? ? remove_meta_prefix : meta_prefix
|
||||
prefix + key.to_s.split(/[-_]/).collect(&:capitalize).join('-')
|
||||
end
|
||||
|
||||
|
|
|
@ -96,8 +96,9 @@ Shindo.tests('Fog::Rackspace::Storage | directory', ['rackspace']) do
|
|||
pending if Fog.mocking?
|
||||
|
||||
model_tests(@service.directories, directory_attributes, Fog.mocking?) do
|
||||
tests('sets metadata on create').returns({:draft => 'true'}) do
|
||||
tests('sets metadata on create').returns('true') do
|
||||
@instance.metadata.data
|
||||
container_meta_attributes["X-Container-Meta-Draft"]
|
||||
end
|
||||
tests('update metadata').returns({"X-Container-Meta-Draft"=>"true", "X-Container-Meta-Color"=>"green"}) do
|
||||
@instance.metadata[:color] = 'green'
|
||||
|
@ -122,6 +123,18 @@ Shindo.tests('Fog::Rackspace::Storage | directory', ['rackspace']) do
|
|||
returns('true') { dir.metadata[:list_test] }
|
||||
end
|
||||
|
||||
tests("should reload metadata after calling reload").returns("42") do
|
||||
@service.put_container @instance.key, "X-Container-Meta-Answer" => 42
|
||||
@instance.reload
|
||||
@instance.metadata[:answer]
|
||||
end
|
||||
|
||||
tests("should reload metadata after calling reload").returns("42") do
|
||||
@service.put_container @instance.key, "X-Container-Meta-Answer" => 42
|
||||
@instance.reload
|
||||
@instance.metadata[:answer]
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -2,8 +2,8 @@ Shindo.tests('Fog::Rackspace::Storage | file', ['rackspace']) do
|
|||
|
||||
pending if Fog.mocking?
|
||||
|
||||
def object_meta_attributes
|
||||
@instance.service.head_object(@directory.key, @instance.key).headers.reject {|k, v| !(k =~ /X-Object-Meta-/)}
|
||||
def object_meta_attributes(file=@instance)
|
||||
@instance.service.head_object(@directory.key, file.key).headers.reject {|k, v| !(k =~ /X-Object-Meta-/)}
|
||||
end
|
||||
|
||||
def clear_metadata
|
||||
|
@ -35,7 +35,7 @@ Shindo.tests('Fog::Rackspace::Storage | file', ['rackspace']) do
|
|||
model_tests(@directory.files, file_attributes, Fog.mocking?) do
|
||||
|
||||
tests("#metadata should load empty metadata").returns({}) do
|
||||
@instance.metadata
|
||||
@instance.metadata.data
|
||||
end
|
||||
|
||||
tests('#save') do
|
||||
|
@ -79,6 +79,15 @@ Shindo.tests('Fog::Rackspace::Storage | file', ['rackspace']) do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
begin
|
||||
tests("sets metadata on create").returns("true") do
|
||||
@file = @directory.files.create :key => 'meta-test', :body => lorem_file, :metadata => {:works => true }
|
||||
object_meta_attributes(@file)["X-Object-Meta-Works"]
|
||||
end
|
||||
ensure
|
||||
@file.destroy if @file
|
||||
end
|
||||
|
||||
tests('urls') do
|
||||
tests('no CDN') do
|
||||
|
|
|
@ -1,35 +1,40 @@
|
|||
require 'fog/rackspace/models/storage/metadata'
|
||||
require 'fog/rackspace/models/storage/directory'
|
||||
require 'fog/rackspace/models/storage/file'
|
||||
|
||||
Shindo.tests('Fog::Rackspace::Storage | metadata', ['rackspace']) do
|
||||
|
||||
tests('#to_key') do
|
||||
tests('valid key').returns(:image_size) do
|
||||
Fog::Storage::Rackspace::Metadata.send(:to_key, "X-Container-Meta-Image-Size")
|
||||
tests('Directory') do
|
||||
@directory = Fog::Storage::Rackspace::Directory.new
|
||||
tests('#to_key') do
|
||||
tests('valid key').returns(:image_size) do
|
||||
metadata = Fog::Storage::Rackspace::Metadata.new @directory
|
||||
metadata.send(:to_key, "X-Container-Meta-Image-Size")
|
||||
end
|
||||
tests('invalid key').returns(nil) do
|
||||
metadata = Fog::Storage::Rackspace::Metadata.new @directory
|
||||
metadata.send(:to_key, "bad-key")
|
||||
end
|
||||
end
|
||||
tests('invalid key').returns(nil) do
|
||||
Fog::Storage::Rackspace::Metadata.send(:to_key, "bad-key")
|
||||
end
|
||||
end
|
||||
|
||||
tests('#to_header_key') do
|
||||
metadata = Fog::Storage::Rackspace::Metadata.new
|
||||
tests('#to_header_key') do
|
||||
metadata = Fog::Storage::Rackspace::Metadata.new @directory
|
||||
|
||||
tests('key to add').returns("X-Container-Meta-Thumbnail-Image") do
|
||||
metadata.send(:to_header_key, :thumbnail_image, true)
|
||||
tests('key to add').returns("X-Container-Meta-Thumbnail-Image") do
|
||||
metadata.send(:to_header_key, :thumbnail_image, true)
|
||||
end
|
||||
|
||||
tests('key to remove').returns("X-Remove-Container-Meta-Thumbnail-Image") do
|
||||
metadata.send(:to_header_key, :thumbnail_image, nil)
|
||||
end
|
||||
end
|
||||
|
||||
tests('key to remove').returns("X-Remove-Container-Meta-Thumbnail-Image") do
|
||||
metadata.send(:to_header_key, :thumbnail_image, nil)
|
||||
end
|
||||
end
|
||||
|
||||
tests('#to_headers').returns({"X-Container-Meta-Preview"=>true, "X-Remove-Container-Meta-Delete-Me"=>1}) do
|
||||
metadata = Fog::Storage::Rackspace::Metadata.new
|
||||
metadata[:preview] = true
|
||||
metadata[:delete_me] = nil
|
||||
tests('#to_headers').returns({"X-Container-Meta-Preview"=>true, "X-Remove-Container-Meta-Delete-Me"=>1}) do
|
||||
metadata = Fog::Storage::Rackspace::Metadata.new @directory
|
||||
metadata[:preview] = true
|
||||
metadata[:delete_me] = nil
|
||||
|
||||
metadata.to_headers
|
||||
end
|
||||
metadata.to_headers
|
||||
end
|
||||
|
||||
tests("#from_headers").returns({:my_boolean=>"true", :my_integer=>"42", :my_string=>"I am a string"}) do
|
||||
headers = {
|
||||
|
@ -38,30 +43,84 @@ Shindo.tests('Fog::Rackspace::Storage | metadata', ['rackspace']) do
|
|||
"X-Container-Meta-My-String"=> "I am a string"
|
||||
}
|
||||
|
||||
metadata = Fog::Storage::Rackspace::Metadata.from_headers headers
|
||||
metadata.data
|
||||
end
|
||||
metadata = Fog::Storage::Rackspace::Metadata.from_headers @directory, headers
|
||||
metadata.data
|
||||
end
|
||||
|
||||
tests("#delete").returns({"X-Remove-Container-Meta-Delete-Me"=>1}) do
|
||||
metadata = Fog::Storage::Rackspace::Metadata.new
|
||||
metadata.delete(:delete_me)
|
||||
tests("#delete").returns({"X-Remove-Container-Meta-Delete-Me"=>1}) do
|
||||
metadata = Fog::Storage::Rackspace::Metadata.new @directory
|
||||
metadata.delete(:delete_me)
|
||||
|
||||
metadata.to_headers
|
||||
metadata.to_headers
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
tests('File') do
|
||||
@file = Fog::Storage::Rackspace::File.new
|
||||
tests('#to_key') do
|
||||
tests('valid key').returns(:image_size) do
|
||||
metadata = Fog::Storage::Rackspace::Metadata.new @file
|
||||
metadata.send(:to_key, "X-Object-Meta-Image-Size")
|
||||
end
|
||||
tests('invalid key').returns(nil) do
|
||||
metadata = Fog::Storage::Rackspace::Metadata.new @file
|
||||
metadata.send(:to_key, "bad-key")
|
||||
end
|
||||
end
|
||||
|
||||
tests('#to_header_key') do
|
||||
metadata = Fog::Storage::Rackspace::Metadata.new @file
|
||||
|
||||
tests('key to add').returns("X-Object-Meta-Thumbnail-Image") do
|
||||
metadata.send(:to_header_key, :thumbnail_image, true)
|
||||
end
|
||||
|
||||
tests('key to remove').returns("X-Remove-Object-Meta-Thumbnail-Image") do
|
||||
metadata.send(:to_header_key, :thumbnail_image, nil)
|
||||
end
|
||||
end
|
||||
|
||||
tests('#to_headers').returns({"X-Object-Meta-Preview"=>true, "X-Remove-Object-Meta-Delete-Me"=>1}) do
|
||||
metadata = Fog::Storage::Rackspace::Metadata.new @file
|
||||
metadata[:preview] = true
|
||||
metadata[:delete_me] = nil
|
||||
|
||||
metadata.to_headers
|
||||
end
|
||||
|
||||
tests("#from_headers").returns({:my_boolean=>"true", :my_integer=>"42", :my_string=>"I am a string"}) do
|
||||
headers = {
|
||||
"X-Object-Meta-My-Integer"=> "42",
|
||||
"X-Object-Meta-My-Boolean"=> "true",
|
||||
"X-Object-Meta-My-String"=> "I am a string"
|
||||
}
|
||||
|
||||
metadata = Fog::Storage::Rackspace::Metadata.from_headers @file, headers
|
||||
metadata.data
|
||||
end
|
||||
|
||||
tests("#delete").returns({"X-Remove-Object-Meta-Delete-Me"=>1}) do
|
||||
metadata = Fog::Storage::Rackspace::Metadata.new @file
|
||||
metadata.delete(:delete_me)
|
||||
|
||||
metadata.to_headers
|
||||
end
|
||||
end
|
||||
|
||||
tests("#respond_to?") do
|
||||
tests('Should respond to all of the methods in Hash class').returns(true) do
|
||||
metadata = Fog::Storage::Rackspace::Metadata.new
|
||||
metadata = Fog::Storage::Rackspace::Metadata.new @file
|
||||
Hash.instance_methods.all? {|method| metadata.respond_to?(method)}
|
||||
end
|
||||
tests('Should respond to all of the methods in the Metadata class').returns(true) do
|
||||
metadata = Fog::Storage::Rackspace::Metadata.new
|
||||
metadata = Fog::Storage::Rackspace::Metadata.new @file
|
||||
metadata.methods.all? {|method| metadata.respond_to?(method)}
|
||||
end
|
||||
end
|
||||
|
||||
tests("#method_missing").returns(true) do
|
||||
metadata = Fog::Storage::Rackspace::Metadata.new
|
||||
metadata = Fog::Storage::Rackspace::Metadata.new @file
|
||||
metadata[:test] = true
|
||||
metadata[:test]
|
||||
end
|
||||
|
|
Loading…
Add table
Reference in a new issue