Class: Miasma::Models::Storage::Azure
- Inherits:
-
Miasma::Models::Storage
- Object
- Miasma::Models::Storage
- Miasma::Models::Storage::Azure
- Includes:
- Contrib::AzureApiCore::ApiCommon
- Defined in:
- lib/miasma/contrib/azure/storage.rb
Constant Summary collapse
- REQUIRED_ATTRIBUTES =
Required attributes for this API
[ :azure_blob_secret_key, :azure_blob_account_name ]
Instance Attribute Summary collapse
Instance Method Summary collapse
-
#all_result_pages(next_token, *result_key) {|options| ... } ⇒ Array
Fetch all results when tokens are being used for paging results.
-
#api_version ⇒ String
Supported API version.
-
#bucket_all ⇒ Array<Models::Storage::Bucket>
Return all buckets.
-
#bucket_destroy(bucket) ⇒ TrueClass, FalseClass
Destroy bucket.
-
#bucket_reload(bucket) ⇒ Models::Storage::Bucket
Reload the bucket.
-
#bucket_save(bucket) ⇒ Models::Storage::Bucket
Save bucket.
-
#endpoint ⇒ String
API endoint.
-
#file_all(bucket) ⇒ Array<File>
Return all files within bucket.
-
#file_body(file) ⇒ IO, HTTP::Response::Body
Fetch the contents of the file.
-
#file_destroy(file) ⇒ TrueClass, FalseClass
Destroy file.
-
#file_filter(bucket, args) ⇒ Array<Models::Storage::File>
Return filtered files.
-
#file_path(file) ⇒ String
Escaped file path.
-
#file_reload(file) ⇒ Models::Storage::File
Reload the file.
-
#file_save(file) ⇒ Models::Storage::File
Save file.
-
#file_url(file, timeout_secs) ⇒ String
Create publicly accessible URL.
-
#initialize(args) ⇒ Azure
constructor
Simple init override to force HOST and adjust region for signatures if required.
Methods included from Contrib::AzureApiCore::ApiCommon
#access_token_expired?, #client_access_token, #connect, #connection, included, #make_request, #oauth_token_buffer_seconds, #oauth_token_information, #perform_request_retry, #request_client_token, #retryable_allowed?, #uri_escape
Constructor Details
#initialize(args) ⇒ Azure
Simple init override to force HOST and adjust region for signatures if required
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/miasma/contrib/azure/storage.rb', line 50 def initialize(args) args = args.to_smash REQUIRED_ATTRIBUTES.each do |name| unless(args[name]) raise ArgumentError.new "Missing required credential `#{name}`!" end end @signer = Contrib::AzureApiCore::SignatureAzure.new( args[:azure_blob_secret_key], args[:azure_blob_account_name] ) @url_signer = Contrib::AzureApiCore::SignatureAzure::SasBlob.new( args[:azure_blob_secret_key], args[:azure_blob_account_name] ) super(args) end |
Instance Attribute Details
#url_signer ⇒ Contrib::AzureApiCore::SignatureAzure::SasBlob (readonly)
46 47 48 |
# File 'lib/miasma/contrib/azure/storage.rb', line 46 def url_signer @url_signer end |
Instance Method Details
#all_result_pages(next_token, *result_key) {|options| ... } ⇒ Array
this is customized to S3 since its API is slightly different than the usual token based fetching
Fetch all results when tokens are being used for paging results
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/miasma/contrib/azure/storage.rb', line 27 def all_result_pages(next_token, *result_key, &block) list = [] = next_token ? Smash.new('marker' => next_token) : Smash.new result = block.call() content = result.get(*result_key.dup) if(content.is_a?(Array)) list += content else list << content end set = result.get(*result_key.slice(0, 2)) if(set.is_a?(Hash) && set['IsTruncated'] && set['Contents']) content_key = (set['Contents'].respond_to?(:last) ? set['Contents'].last : set['Contents'])['Key'] list += all_result_pages(content_key, *result_key, &block) end list.compact end |
#api_version ⇒ String
Returns supported API version.
69 70 71 |
# File 'lib/miasma/contrib/azure/storage.rb', line 69 def api_version '2015-04-05' end |
#bucket_all ⇒ Array<Models::Storage::Bucket>
Return all buckets
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
# File 'lib/miasma/contrib/azure/storage.rb', line 150 def bucket_all result = request( :path => '/', :params => { :comp => 'list' } ) cont = result.get(:body, 'EnumerationResults', 'Containers', 'Container') unless(cont.is_a?(Array)) cont = [cont].compact end cont.map do |bkt| Bucket.new( self, :id => bkt['Name'], :name => bkt['Name'], :custom => bkt['Properties'] ).valid_state end end |
#bucket_destroy(bucket) ⇒ TrueClass, FalseClass
Destroy bucket
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/miasma/contrib/azure/storage.rb', line 105 def bucket_destroy(bucket) if(bucket.persisted?) request( :path => bucket.name, :method => :delete, :expects => 202, :params => { :restype => 'container' } ) true else false end end |
#bucket_reload(bucket) ⇒ Models::Storage::Bucket
Reload the bucket
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/miasma/contrib/azure/storage.rb', line 125 def bucket_reload(bucket) if(bucket.persisted?) begin result = request( :path => bucket.name, :method => :head, :params => { :restype => 'container' } ) rescue Error::ApiError::RequestError => e if(e.response.status == 404) bucket.data.clear bucket.dirty.clear else raise end end end bucket end |
#bucket_save(bucket) ⇒ Models::Storage::Bucket
Save bucket
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/miasma/contrib/azure/storage.rb', line 82 def bucket_save(bucket) unless(bucket.persisted?) request( :path => bucket.name, :method => :put, :expects => 201, :params => { :restype => 'container' }, :headers => { 'Content-Length' => 0 } ) bucket.id = bucket.name bucket.valid_state end bucket end |
#endpoint ⇒ String
Returns API endoint.
74 75 76 |
# File 'lib/miasma/contrib/azure/storage.rb', line 74 def endpoint "https://#{azure_blob_account_name}.blob.core.windows.net" end |
#file_all(bucket) ⇒ Array<File>
Return all files within bucket
199 200 201 |
# File 'lib/miasma/contrib/azure/storage.rb', line 199 def file_all(bucket) file_filter(bucket, {}) end |
#file_body(file) ⇒ IO, HTTP::Response::Body
Fetch the contents of the file
320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 |
# File 'lib/miasma/contrib/azure/storage.rb', line 320 def file_body(file) file_content = nil if(file.persisted?) result = request( :path => [file.bucket.name, file_path(file)].join('/'), :disable_body_extraction => true ) content = result[:body] begin if(content.is_a?(String)) file_content = StringIO.new(content) else if(content.respond_to?(:stream!)) content.stream! end file_content = content end rescue HTTP::StateError file_content = StringIO.new(content.to_s) end else file_content = StringIO.new('') end File::Streamable.new(file_content) end |
#file_destroy(file) ⇒ TrueClass, FalseClass
Destroy file
254 255 256 257 258 259 260 261 262 263 264 265 |
# File 'lib/miasma/contrib/azure/storage.rb', line 254 def file_destroy(file) if(file.persisted?) request( :method => :delete, :path => [file.bucket.name, file_path(file)].join('/'), :expects => 202 ) true else false end end |
#file_filter(bucket, args) ⇒ Array<Models::Storage::File>
Return filtered files
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
# File 'lib/miasma/contrib/azure/storage.rb', line 175 def file_filter(bucket, args) result = request( :path => bucket.name, :params => { :restype => 'container', :comp => 'list', :prefix => args[:prefix] } ) [result.get(:body, 'EnumerationResults', 'Blobs', 'Blob')].flatten.compact.map do |file| File.new( bucket, :id => ::File.join(bucket.name, file['Name']), :name => file['Name'], :updated => file.get('Properties', 'Last_Modified'), :size => file.get('Properties', 'Content_Length').to_i ).valid_state end end |
#file_path(file) ⇒ String
Returns escaped file path.
347 348 349 350 351 |
# File 'lib/miasma/contrib/azure/storage.rb', line 347 def file_path(file) file.name.split('/').map do |part| uri_escape(part) end.join('/') end |
#file_reload(file) ⇒ Models::Storage::File
Reload the file
271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 |
# File 'lib/miasma/contrib/azure/storage.rb', line 271 def file_reload(file) if(file.persisted?) name = file.name result = request( :method => :head, :path => [file.bucket.name, file_path(file)].join('/') ) file.data.clear && file.dirty.clear info = result[:headers] file.load_data( :id => [file.bucket.name, name].join('/'), :name => name, :updated => info[:last_modified], :etag => info[:etag], :size => info[:content_length].to_i, :content_type => info[:content_type] ).valid_state end file end |
#file_save(file) ⇒ Models::Storage::File
Save file
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 |
# File 'lib/miasma/contrib/azure/storage.rb', line 207 def file_save(file) if(file.dirty?) file.load_data(file.attributes) args = Smash.new headers = Smash[ Smash.new( :content_type => 'Content-Type', :content_disposition => 'Content-Disposition', :content_encoding => 'Content-Encoding' ).map do |attr, key| if(file.attributes[attr]) [key, file.attributes[attr]] end end.compact ] unless(headers.empty?) args[:headers] = headers end if(file.attributes[:body].respond_to?(:readpartial)) args.set(:headers, 'Content-Length', file.body.size.to_s) file.body.rewind args[:body] = file.body.readpartial(file.body.size) file.body.rewind else args.set(:headers, 'Content-Length', 0) end args.set(:headers, 'x-ms-blob-type', 'BlockBlob') result = request( args.merge( Smash.new( :method => :put, :path => [file.bucket.name, file_path(file)].join('/'), :expects => 201 ) ) ) file.etag = result.get(:headers, :etag) file.id = ::File.join(file.bucket.name, file.name) file.valid_state end file end |
#file_url(file, timeout_secs) ⇒ String
Create publicly accessible URL
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 |
# File 'lib/miasma/contrib/azure/storage.rb', line 296 def file_url(file, timeout_secs) object_path = [file.bucket.name, file_path(file)].join('/') sign_args = Smash.new( :params => Smash.new( :sr => 'b', :sv => api_version, :se => (Time.now.utc + timeout_secs).iso8601, :sp => 'r' ) ) signature = url_signer.generate(:get, object_path, sign_args) uri = URI.parse([endpoint, object_path].join('/')) uri.query = URI.encode_www_form( sign_args[:params].merge( :sig => signature ) ) uri.to_s end |