Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Directories+Directory implementation

  • Loading branch information...
commit 3630815c1074ccb6eb088d2cb8d52068be752422 1 parent 314d316
@shadysayed authored
View
3  lib/fog-azure.rb
@@ -7,8 +7,5 @@ module Fog
module Azure
extend Fog::Provider
service :storage, 'azure/storage', 'Storage'
- def self.test
- "hello"
- end
end
end
View
50 lib/fog/azure/models/storage/directory.rb
@@ -4,15 +4,65 @@ module Fog
module Storage
class Azure
class Directory < Fog::Model
+
+ VALID_ALCS = ['container', 'blob', nil]
+
identity :key, :aliases => ['Name']
attribute :last_modified, :aliases => ['Last-Modified']
attribute :url, :aliases => ['Url']
attribute :etag, :aliases => ['Etag']
attribute :metadata, :aliases => ['Metadata']
+ attr_reader :acl
+
+
+ def acl=(new_acl)
+ unless VALID_ALCS.include? new_acl
+ raise ArgumentError.new("acl must be one of [#{VALID_ALCS.join(', ')}]")
+ else
+ @acl = new_acl
+ end
+ end
+
+ def destroy
+ requires :key
+ connection.delete_container(key)
+ true
+ rescue Excon::Errors::NotFound => e
+ false
+ end
+
+
def files
@files ||= Fog::Storage::Azure::Files.new(directory: self, connection: connection)
end
+
+ def public=(new_public)
+ self.acl = new_public ? 'blob' : nil
+ new_public
+ end
+
+ def public_url
+ requires :key
+ # raise connection.get_container_acl(key).headers.inspect
+ if ['container', 'blob'].include? connection.get_container_acl(key).headers['x-ms-blob-public-access']
+ ::File.join "#{connection.scheme}://#{connection.host}", key
+ else
+ nil
+ end
+ end
+
+ def save
+ requires :key
+
+ options = {}
+ options['x-ms-blob-public-access'] = acl if acl
+
+ connection.create_container(key, options)
+
+ true
+ end
+
end
end
end
View
54 lib/fog/azure/models/storage/file.rb
@@ -8,6 +8,60 @@ class File < Fog::Model
identity :key, :aliases => 'Name'
+ attr_writer :body
+ attribute :cache_control, :aliases => 'Cache-Control'
+ # attribute :content_disposition, :aliases => 'Content-Disposition'
+ attribute :content_encoding, :aliases => 'Content-Encoding'
+ attribute :content_length, :aliases => ['Content-Length', 'Size'], :type => :integer
+ attribute :content_md5, :aliases => 'Content-MD5'
+ attribute :content_type, :aliases => 'Content-Type'
+ attribute :etag, :aliases => ['Etag', 'ETag']
+ attribute :expires, :aliases => 'Expires'
+ attribute :last_modified, :aliases => ['Last-Modified', 'LastModified'], :type => :time
+
+ # Block size for the using the block api
+ # Use small sizes to conserve memory (the max allowed by API is 4 Megs)
+ attr_accessor :block_size
+
+ def body
+ attributes[:body] ||= if last_modified && (file = collection.get(identity))
+ file.body
+ else
+ ''
+ end
+ end
+
+ def body=(new_body)
+ attributes[:body] = new_body
+ end
+
+ def directory
+ @directory
+ end
+
+
+ def copy(target_directory_key, target_file_key, options ={})
+
+ end
+
+ def destroy(options = {})
+
+ end
+
+ def save(options = {})
+
+ end
+
+ private
+
+ def directory=(new_directory)
+ @directory = new_directory
+ end
+
+ def save_with_blocks(options)
+
+ end
+
end
end
end
View
30 lib/fog/azure/models/storage/files.rb
@@ -42,8 +42,24 @@ def all(options = {})
end
end
- def get(key, options = {}, &block)
-
+ def get(key, options = {})
+ requires :directory
+ response = connection.get_blob(directory.key, key, options)
+ file_attributes = response.headers.merge({
+ body: data.body,
+ key: key
+ })
+ normalise_headers(file_attributes)
+ new(file_attributes)
+ rescue Excon::Errors::NotFound => error
+ end
+
+ def get_url(key)
+ requires :directory
+ end
+
+ def head(key, options = {})
+ requires :directory
end
alias :each_file_this_page :each
@@ -59,6 +75,16 @@ def each
self
end
+ def new(attributes = {})
+ requires :directory
+ super({ :directory => directory }.merge!(attributes))
+ end
+
+ # Borrowed from fog
+ def normalise_headers(headers)
+ headers['Last-Modified'] = Time.parse(headers['Last-Modified'])
+ headers['ETag'].gsub!('"','')
+ end
end
end
end
View
23 lib/fog/azure/requests/storage/create_container.rb
@@ -0,0 +1,23 @@
+module Fog
+ module Storage
+ class Azure
+ class Real
+ def create_container(key, options = {})
+ request(
+ expects: [201],
+ path: key,
+ method: 'PUT',
+ headers: options,
+ query: {
+ 'restype' => 'container'
+ }
+ )
+ end
+ end
+ class Mock
+ def create_container(key, options = {})
+ end
+ end
+ end
+ end
+end
View
22 lib/fog/azure/requests/storage/delete_container.rb
@@ -0,0 +1,22 @@
+module Fog
+ module Storage
+ class Azure
+ class Real
+ def delete_container(key)
+ request(
+ expects: [202],
+ path: key,
+ method: 'DELETE',
+ query: {
+ 'restype' => 'container'
+ }
+ )
+ end
+ end
+ class Mock
+ def delete_container(key, options = {})
+ end
+ end
+ end
+ end
+end
View
33 lib/fog/azure/requests/storage/get_blob.rb
@@ -0,0 +1,33 @@
+module Fog
+ module Storage
+ class Azure
+ class Real
+ def get_blob(container, path, options = {}, &block)
+ unless container
+ raise ArgumentError.new("container is required")
+ end
+ unless path
+ raise ArgumentError.new("path is required")
+ end
+ params = {headers: {}}
+ if snapshot = options.delete('snapshot')
+ params[:query] = {'snapshot' => snapshot}
+ end
+
+ if block_given?
+ params[:response_block] = Proc.new
+ end
+
+ request(params.merge!({
+ expects: [200],
+ method: :get,
+ idempotent: true,
+ path: File.join(container, path) # Fog::Rackspace.escape(path, '/'))
+ }))
+ end
+ end
+ class Mock
+ end
+ end
+ end
+end
View
30 lib/fog/azure/requests/storage/get_blob_properties.rb
@@ -0,0 +1,30 @@
+module Fog
+ module Storage
+ class Azure
+ class Real
+ def get_blob_properties(container, path, options = {})
+ unless container
+ raise ArgumentError.new("container is required")
+ end
+ unless path
+ raise ArgumentError.new("path is required")
+ end
+ params = {headers: {}}
+ if snapshot = options.delete('snapshot')
+ params[:query] = {'snapshot' => snapshot}
+ end
+
+
+ request(params.merge!({
+ expects: [200],
+ method: 'HEAD',
+ idempotent: true,
+ path: File.join(container, path) # Fog::Rackspace.escape(path, '/'))
+ }))
+ end
+ end
+ class Mock
+ end
+ end
+ end
+end
View
24 lib/fog/azure/requests/storage/get_container_acl.rb
@@ -0,0 +1,24 @@
+module Fog
+ module Storage
+ class Azure
+ class Real
+ def get_container_acl(container)
+ # TODO: We might need to make a parser or something for the full implementation
+ request(
+ path: container,
+ method: :get,
+ query:{
+ 'restype' => 'container',
+ 'comp' => 'acl'
+ }
+ )
+ end
+ end
+ class Mock
+ def get_container_acl(container)
+
+ end
+ end
+ end
+ end
+end
View
28 lib/fog/azure/requests/storage/get_container_properties.rb
@@ -0,0 +1,28 @@
+module Fog
+ module Storage
+ class Azure
+ class Real
+ # no parser is needed we read from headers
+ #require 'fog/azure/parsers/storage/get_container_properties'
+
+ def get_container_properties(name, options = {})
+ # This operation will only nead to change the query string
+ # So the options hash is passed to the query and not headers
+ request(
+ expects: 200,
+ headers: {},
+ path: name,
+ method: :get,
+ query: {
+ 'restype' => 'container'
+ }.merge!(options || {})
+ )
+ end
+ end
+ class Mock
+ def get_container_properties(options = {})
+ end
+ end
+ end
+ end
+end
View
60 lib/fog/azure/requests/storage/set_container_acl.rb
@@ -0,0 +1,60 @@
+module Fog
+ module Storage
+ class Azure
+ class Real
+ # no parser is needed we read from headers
+ #require 'fog/azure/parsers/storage/get_container_properties'
+
+ def set_container_acl(key, acl = nil, signed_identifiers = nil)
+
+ unless ['container', 'blob', nil].include? acl
+ raise Excon::Errors::BadRequest.new('invalid x-ms-blob-public-access')
+ end
+ # This operation will only nead to change the query string
+ # So the options hash is passed to the query and not headers
+ headers = {}
+ body = ''
+ if acl
+ headers['x-ms-blob-public-access'] = acl
+ end
+ if signed_identifiers
+ identifiers_xml = signed_identifiers.map{ |identifier|
+ <<-XML
+ <SignedIdentifier>
+ <Id>#{identifier.id}</Id>
+ <AccessPolicy>
+ <Start>#{identifier.access_policy.start}</Start>
+ <Expiry>#{identifier.access_policy.expiry}</Expiry>
+ <Permission>#{identifier.access_policy.permission}</Permission>
+ </AccessPolicy>
+ </SignedIdentifier>
+XML
+ }
+
+ body = <<-XML
+<?xml version="1.0" encoding="utf-8"?>
+<SignedIdentifiers>
+#{identifiers_xml}
+</SignedIdentifiers>
+XML
+ end
+ request(
+ expects: 200,
+ headers: headers,
+ path: key,
+ method: 'PUT',
+ body: body,
+ query: {
+ 'restype' => 'container',
+ 'comp' => 'acl'
+ }#.merge!(options || {})
+ )
+ end
+ end
+ class Mock
+ def set_container_acl(key, acl = nil, signed_identifiers = nil)
+ end
+ end
+ end
+ end
+end
View
26 lib/fog/azure/storage.rb
@@ -22,18 +22,18 @@ class Azure < Fog::Service
request :list_containers
# request :set_blob_service_properties
# request :get_blob_service_properties
- # request :create_container
- # request :get_container_properties
+ request :create_container
+ request :get_container_properties
# request :get_container_metadata
# request :set_container_metadata
- # request :get_container_acl
- # request :set_container_acl
+ request :get_container_acl
+ request :set_container_acl
# request :lease_container
- # request :delete_container
+ request :delete_container
request :list_blobs
# request :put_blob
- # request :get_blob
- # request :get_blob_properties
+ request :get_blob
+ request :get_blob_properties
# request :set_blob_properties
# request :get_blob_metadata
# request :set_blob_metadata
@@ -85,6 +85,10 @@ def extract_ms_metadata(dict)
class Real
include Utils
+ attr_reader :host
+ attr_reader :scheme
+ attr_reader :path
+
# Initialize connection to azure blob store
#
# ==== Notes
@@ -145,9 +149,17 @@ def request(params, &block)
params[:path] ||= '/'
headers = params[:headers]
+ if params[:method] && ![:get, 'GET'].include?(params[:method])
+ content_length = 0
+ if params[:body]
+ content_length = params[:body].size
+ end
+ headers["Content-Length"] = content_length
+ end
headers["x-ms-Date"] = Time.new.httpdate
headers["x-ms-version"] = "2009-09-19"
headers["Authorization"] = "SharedKey #{@azure_storage_account_name}:#{get_signature(params)}"
+ # raise headers.inspect
begin
response = @connection.request(params, &block)
# rescue Excon::Errors::SocketError => e
Please sign in to comment.
Something went wrong with that request. Please try again.