azure 0.0.0 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +3 -0
- data/Gemfile.lock +36 -0
- data/README.md +3 -0
- data/Rakefile +81 -0
- data/azure.gemspec +20 -9
- data/lib/azure.rb +4 -0
- data/lib/azure/atom.rb +170 -0
- data/lib/azure/auth.rb +29 -0
- data/lib/azure/blobs.rb +620 -0
- data/lib/azure/blobs/blob.rb +360 -0
- data/lib/azure/blobs/container.rb +209 -0
- data/lib/azure/blobs/service.rb +396 -0
- data/lib/azure/blobs/shared_access_signature.rb +84 -0
- data/lib/azure/blobs/uri.rb +60 -0
- data/lib/azure/configuration.rb +121 -0
- data/lib/azure/core/auth/shared_key.rb +95 -0
- data/lib/azure/core/auth/shared_key_lite.rb +34 -0
- data/lib/azure/core/collection.rb +118 -0
- data/lib/azure/core/service.rb +43 -0
- data/lib/azure/core/signer.rb +32 -0
- data/lib/azure/core/utils/interval.rb +97 -0
- data/lib/azure/core/utils/queryable.rb +74 -0
- data/lib/azure/core/utils/storage_service_properties.rb +83 -0
- data/lib/azure/core/utils/string.rb +59 -0
- data/lib/azure/error.rb +72 -0
- data/lib/azure/queues.rb +272 -0
- data/lib/azure/queues/message.rb +174 -0
- data/lib/azure/queues/queue.rb +187 -0
- data/lib/azure/queues/service.rb +263 -0
- data/lib/azure/queues/service_properties.rb +152 -0
- data/lib/azure/queues/uri.rb +78 -0
- data/lib/azure/request.rb +102 -0
- data/lib/azure/response.rb +93 -0
- data/lib/azure/service_bus.rb +4 -0
- data/lib/azure/service_bus/auth/authorizer.rb +22 -0
- data/lib/azure/service_bus/auth/uri.rb +52 -0
- data/lib/azure/service_bus/auth/wrap.rb +37 -0
- data/lib/azure/service_bus/auth/wrap_service.rb +76 -0
- data/lib/azure/service_bus/auth/wrap_token.rb +45 -0
- data/lib/azure/service_bus/auth/wrap_token_manager.rb +46 -0
- data/lib/azure/service_bus/brokered_message.rb +139 -0
- data/lib/azure/service_bus/brokered_message_serializer.rb +113 -0
- data/lib/azure/service_bus/queues.rb +194 -0
- data/lib/azure/service_bus/queues/queue.rb +100 -0
- data/lib/azure/service_bus/queues/queue_serializer.rb +51 -0
- data/lib/azure/service_bus/queues/service.rb +154 -0
- data/lib/azure/service_bus/queues/uri.rb +80 -0
- data/lib/azure/service_bus/rules.rb +110 -0
- data/lib/azure/service_bus/rules/rule.rb +97 -0
- data/lib/azure/service_bus/rules/service.rb +122 -0
- data/lib/azure/service_bus/rules/uri.rb +39 -0
- data/lib/azure/service_bus/service_bus_service.rb +22 -0
- data/lib/azure/service_bus/subscriptions.rb +170 -0
- data/lib/azure/service_bus/subscriptions/service.rb +133 -0
- data/lib/azure/service_bus/subscriptions/subscription.rb +164 -0
- data/lib/azure/service_bus/subscriptions/subscription_serializer.rb +74 -0
- data/lib/azure/service_bus/subscriptions/uri.rb +71 -0
- data/lib/azure/service_bus/topics.rb +120 -0
- data/lib/azure/service_bus/topics/service.rb +98 -0
- data/lib/azure/service_bus/topics/topic.rb +122 -0
- data/lib/azure/service_bus/topics/topic_serializer.rb +44 -0
- data/lib/azure/service_bus/topics/uri.rb +58 -0
- data/lib/azure/service_runtime/client/goal_state_pipe_monitor.rb +21 -0
- data/lib/azure/service_runtime/client/goal_state_protocol.rb +18 -0
- data/lib/azure/service_runtime/client/runtime_client.rb +135 -0
- data/lib/azure/service_runtime/deployment.rb +24 -0
- data/lib/azure/service_runtime/local_resource.rb +15 -0
- data/lib/azure/service_runtime/role.rb +17 -0
- data/lib/azure/service_runtime/role_environment.rb +206 -0
- data/lib/azure/service_runtime/role_environment_change.rb +32 -0
- data/lib/azure/service_runtime/role_instance.rb +35 -0
- data/lib/azure/service_runtime/role_instance_endpoint.rb +14 -0
- data/lib/azure/tables.rb +215 -0
- data/lib/azure/tables/auth/shared_key.rb +71 -0
- data/lib/azure/tables/auth/shared_key_lite.rb +30 -0
- data/lib/azure/tables/entities_collection.rb +66 -0
- data/lib/azure/tables/entity.rb +127 -0
- data/lib/azure/tables/service.rb +211 -0
- data/lib/azure/tables/table.rb +129 -0
- data/lib/azure/tables/tables_collection.rb +62 -0
- data/lib/azure/tables/types.rb +65 -0
- data/lib/azure/tables/uri.rb +62 -0
- data/test/fixtures/32px-fulls-black.jpg +0 -0
- data/test/fixtures/all_containers.xml +20 -0
- data/test/fixtures/all_tables.xml +22 -0
- data/test/fixtures/create_table_response_entry.xml +15 -0
- data/test/fixtures/error.xml +5 -0
- data/test/fixtures/insert_entity_response_entry.xml +25 -0
- data/test/fixtures/messages.xml +12 -0
- data/test/fixtures/query_entities_empty_response.xml +7 -0
- data/test/fixtures/query_entities_response.xml +45 -0
- data/test/fixtures/queue_service_properties.xml +22 -0
- data/test/fixtures/queue_service_properties_original.xml +19 -0
- data/test/fixtures/queues.xml +16 -0
- data/test/fixtures/sb_default_create_queue_response.xml +23 -0
- data/test/fixtures/sb_default_create_topic_response.xml +18 -0
- data/test/fixtures/sb_get_access_token_response.txt +1 -0
- data/test/fixtures/sb_queues_runtime_peek_message_response_headers.txt +9 -0
- data/test/integration/blobs/auth_test.rb +19 -0
- data/test/integration/blobs/blob_test.rb +61 -0
- data/test/integration/blobs/clear_page_range_test.rb +19 -0
- data/test/integration/blobs/copy_test.rb +33 -0
- data/test/integration/blobs/create_blobs_test.rb +51 -0
- data/test/integration/blobs/create_container_test.rb +13 -0
- data/test/integration/blobs/create_snapshot_test.rb +17 -0
- data/test/integration/blobs/delete_blob_snapshots_test.rb +19 -0
- data/test/integration/blobs/delete_blobs_test.rb +25 -0
- data/test/integration/blobs/delete_container_test.rb +24 -0
- data/test/integration/blobs/delete_snapshot_test.rb +17 -0
- data/test/integration/blobs/get_blob_snapshot_test.rb +18 -0
- data/test/integration/blobs/get_blobs_test.rb +31 -0
- data/test/integration/blobs/get_page_range_test.rb +19 -0
- data/test/integration/blobs/list_blobs_test.rb +39 -0
- data/test/integration/blobs/list_containers_test.rb +28 -0
- data/test/integration/blobs/manage_blob_leases_test.rb +45 -0
- data/test/integration/blobs/manage_blob_metadata_test.rb +51 -0
- data/test/integration/blobs/manage_blob_properties_test.rb +25 -0
- data/test/integration/blobs/manage_blob_service_properties_test.rb +38 -0
- data/test/integration/blobs/manage_container_metadata_test.rb +46 -0
- data/test/integration/blobs/manage_container_permissions_test.rb +17 -0
- data/test/integration/blobs/update_page_range_test.rb +20 -0
- data/test/integration/queues/clear_messages_test.rb +22 -0
- data/test/integration/queues/create_queue_test.rb +13 -0
- data/test/integration/queues/delete_message_test.rb +42 -0
- data/test/integration/queues/delete_queue_test.rb +24 -0
- data/test/integration/queues/get_messages_test.rb +39 -0
- data/test/integration/queues/list_queues_test.rb +43 -0
- data/test/integration/queues/manage_queue_metadata_test.rb +45 -0
- data/test/integration/queues/manage_queue_service_properties_test.rb +27 -0
- data/test/integration/queues/peek_messages_test.rb +55 -0
- data/test/integration/queues/put_message_test.rb +31 -0
- data/test/integration/queues/update_message_test.rb +46 -0
- data/test/integration/service_bus/auth_test.rb +18 -0
- data/test/integration/service_bus/queues/create_queue_test.rb +25 -0
- data/test/integration/service_bus/queues/delete_message_from_queue_test.rb +29 -0
- data/test/integration/service_bus/queues/delete_queue_test.rb +25 -0
- data/test/integration/service_bus/queues/get_queue_test.rb +23 -0
- data/test/integration/service_bus/queues/list_queues_test.rb +39 -0
- data/test/integration/service_bus/queues/peek_message_from_queue_test.rb +34 -0
- data/test/integration/service_bus/queues/read_and_delete_message_from_queue_test.rb +31 -0
- data/test/integration/service_bus/queues/send_message_to_queue_test.rb +22 -0
- data/test/integration/service_bus/queues/unlock_message_from_queue_test.rb +36 -0
- data/test/integration/service_bus/rules/create_rule_test.rb +19 -0
- data/test/integration/service_bus/rules/delete_rule_test.rb +17 -0
- data/test/integration/service_bus/rules/get_rule_test.rb +21 -0
- data/test/integration/service_bus/rules/list_rules_test.rb +24 -0
- data/test/integration/service_bus/rules/rule_test.rb +16 -0
- data/test/integration/service_bus/subscriptions/create_subscription_test.rb +25 -0
- data/test/integration/service_bus/subscriptions/delete_message_from_subscription_test.rb +31 -0
- data/test/integration/service_bus/subscriptions/delete_subscription_test.rb +30 -0
- data/test/integration/service_bus/subscriptions/fetch_subscription_test.rb +28 -0
- data/test/integration/service_bus/subscriptions/list_subscriptions_test.rb +23 -0
- data/test/integration/service_bus/subscriptions/peek_lock_message_from_subscription_test.rb +42 -0
- data/test/integration/service_bus/subscriptions/read_delete_message_from_subscription_test.rb +36 -0
- data/test/integration/service_bus/subscriptions/subscription_test.rb +31 -0
- data/test/integration/service_bus/subscriptions/unlock_message_from_subscription_test.rb +43 -0
- data/test/integration/service_bus/topics/create_topic_test.rb +25 -0
- data/test/integration/service_bus/topics/delete_topic_test.rb +25 -0
- data/test/integration/service_bus/topics/get_topic_test.rb +23 -0
- data/test/integration/service_bus/topics/list_topics_test.rb +39 -0
- data/test/integration/service_bus/topics/send_message_to_topic_test.rb +23 -0
- data/test/integration/tables/auth_test.rb +29 -0
- data/test/integration/tables/creating_tables_test.rb +16 -0
- data/test/integration/tables/delete_entity_test.rb +39 -0
- data/test/integration/tables/deleting_table_test.rb +22 -0
- data/test/integration/tables/insert_entity_test.rb +23 -0
- data/test/integration/tables/merge_entity_test.rb +28 -0
- data/test/integration/tables/query_entities_test.rb +131 -0
- data/test/integration/tables/query_tables_test.rb +63 -0
- data/test/integration/tables/update_entity_test.rb +54 -0
- data/test/integration/test_helper.rb +14 -0
- data/test/support/blobs.rb +12 -0
- data/test/support/env.rb +5 -0
- data/test/support/fixtures.rb +22 -0
- data/test/support/stubs.rb +28 -0
- data/test/support/table_names.rb +44 -0
- data/test/test_helper.rb +10 -0
- data/test/unit/atom_test.rb +58 -0
- data/test/unit/auth_test.rb +24 -0
- data/test/unit/blobs/blob_test.rb +5 -0
- data/test/unit/blobs/container_test.rb +67 -0
- data/test/unit/blobs/service_test.rb +17 -0
- data/test/unit/blobs/shared_access_signature_test.rb +66 -0
- data/test/unit/blobs_test.rb +156 -0
- data/test/unit/core/service_test.rb +57 -0
- data/test/unit/core/utils/interval_test.rb +70 -0
- data/test/unit/core/utils/queryable_test.rb +69 -0
- data/test/unit/core/utils/storage_service_properties_test.rb +66 -0
- data/test/unit/error_test.rb +39 -0
- data/test/unit/queues/message_test.rb +40 -0
- data/test/unit/queues/queue_test.rb +64 -0
- data/test/unit/queues/service_properties.rb +35 -0
- data/test/unit/request_test.rb +38 -0
- data/test/unit/response_test.rb +43 -0
- data/test/unit/service_bus/auth/authorizer_test.rb +27 -0
- data/test/unit/service_bus/auth/wrap_token_test.rb +28 -0
- data/test/unit/service_bus/queues/queue_test.rb +38 -0
- data/test/unit/service_bus/topics/topic_test.rb +33 -0
- data/test/unit/service_runtime/data/goalstate.xml +9 -0
- data/test/unit/service_runtime/data/roleenvironmentdata.xml +29 -0
- data/test/unit/service_runtime/data/runtime.xml +6 -0
- data/test/unit/service_runtime/role_environment_test.rb +144 -0
- data/test/unit/tables/auth/shared_key_lite_test.rb +39 -0
- data/test/unit/tables/auth/shared_key_test.rb +45 -0
- data/test/unit/tables/entities_collection_test.rb +39 -0
- data/test/unit/tables/entity_test.rb +72 -0
- data/test/unit/tables/table_test.rb +57 -0
- data/test/unit/tables_test.rb +302 -0
- data/test/unit/types_test.rb +67 -0
- metadata +310 -47
- data/LICENSE +0 -0
- data/README +0 -0
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
require "nokogiri"
|
|
2
|
+
require "uri"
|
|
3
|
+
require "azure/error"
|
|
4
|
+
require "azure/blobs"
|
|
5
|
+
require "azure/blobs/uri"
|
|
6
|
+
require "digest/sha1"
|
|
7
|
+
|
|
8
|
+
module Azure
|
|
9
|
+
module Blobs
|
|
10
|
+
class Blob
|
|
11
|
+
include ErrorHandler
|
|
12
|
+
|
|
13
|
+
# List of valid property names.
|
|
14
|
+
PROPERTIES = [
|
|
15
|
+
"content-length",
|
|
16
|
+
"content-type",
|
|
17
|
+
"content-md5",
|
|
18
|
+
"content-encoding",
|
|
19
|
+
"content-language",
|
|
20
|
+
"cache-control",
|
|
21
|
+
"last-modified",
|
|
22
|
+
"etag",
|
|
23
|
+
"x-ms-lease-status",
|
|
24
|
+
"x-ms-lease-time",
|
|
25
|
+
"x-ms-lease-id",
|
|
26
|
+
"x-ms-blob-sequence-number",
|
|
27
|
+
"x-ms-snapshot"
|
|
28
|
+
].freeze
|
|
29
|
+
|
|
30
|
+
# Public: Get/Set the container where this blob belongs.
|
|
31
|
+
attr_accessor :container
|
|
32
|
+
|
|
33
|
+
# Public: Get the name of the blob.
|
|
34
|
+
attr :name
|
|
35
|
+
|
|
36
|
+
# Public: Get the Properties of the blob.
|
|
37
|
+
#
|
|
38
|
+
# Following are *Optional*
|
|
39
|
+
# - "x-ms-blob-cache-control" Modifies the cache control string for the blob.
|
|
40
|
+
# - "x-ms-blob-content-type" Sets the blob’s content type.
|
|
41
|
+
# - "x-ms-blob-content-md5" Sets the blob's MD5 hash.
|
|
42
|
+
# - "x-ms-blob-content-encoding" Sets the blob's content encoding.
|
|
43
|
+
# - "x-ms-blob-content-languag" Sets the blob's content language.
|
|
44
|
+
#
|
|
45
|
+
# Following may be *Required*
|
|
46
|
+
# - "x-ms-lease-id" Required if the blob has an active lease.
|
|
47
|
+
#
|
|
48
|
+
# Following properties only apply to Page Blobs.
|
|
49
|
+
# - Optional "x-ms-blob-content-length" Resizes a page blob to the specified size.
|
|
50
|
+
# If the specified value is less than the current size of the blob, then all
|
|
51
|
+
# pages above the specified value are cleared.
|
|
52
|
+
#
|
|
53
|
+
# - "x-ms-sequence-number-action" Optional, but required if the x-ms-blob-sequence-number
|
|
54
|
+
# header is set for the request. Posible values: {max, update, increment}
|
|
55
|
+
#
|
|
56
|
+
# - "x-ms-blob-sequence-number" Optional, but required if the x-ms-sequence-number-action
|
|
57
|
+
# property is set to max or update.
|
|
58
|
+
#
|
|
59
|
+
# See http://msdn.microsoft.com/en-us/library/windowsazure/ee691966.
|
|
60
|
+
attr :properties
|
|
61
|
+
|
|
62
|
+
# Public: Get the Metadata of the blob.
|
|
63
|
+
attr :metadata
|
|
64
|
+
|
|
65
|
+
# Public: Get the Content of the blob.
|
|
66
|
+
attr :content
|
|
67
|
+
|
|
68
|
+
# Public: Initialize a blob from an XML node as returned from an API
|
|
69
|
+
# response.
|
|
70
|
+
#
|
|
71
|
+
# container - A instance of Azure::Blobs::Container
|
|
72
|
+
# node - A Nokogiri::Node.
|
|
73
|
+
#
|
|
74
|
+
# Returns a Blob.
|
|
75
|
+
def self.from_node(node)
|
|
76
|
+
name = (node % "Name").text
|
|
77
|
+
|
|
78
|
+
properties = (node / "Properties *").each_with_object({}) do |no, props|
|
|
79
|
+
props[no.name] = no.text
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
metadata = (node / "Metadata *").each_with_object({}) do |no, meta|
|
|
83
|
+
meta[no.name] = no.text
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
container_name = (node / "Url").text.split("/")[-2..-2].first
|
|
87
|
+
container = Azure::Blobs::Container.new(container_name)
|
|
88
|
+
|
|
89
|
+
new(name, container) do |blob|
|
|
90
|
+
blob.metadata.replace(metadata)
|
|
91
|
+
blob.properties.replace(properties)
|
|
92
|
+
yield blob if block_given?
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Public: Instantiate a blob from an error object.
|
|
97
|
+
#
|
|
98
|
+
# error - An Azure::Error.
|
|
99
|
+
#
|
|
100
|
+
# Returns a Table.
|
|
101
|
+
def self.from_error(error)
|
|
102
|
+
new(nil, nil, nil) do |blob|
|
|
103
|
+
blob.error = error
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Public: Initialize a Blob.
|
|
108
|
+
#
|
|
109
|
+
# name - A String with the name of the Blob.
|
|
110
|
+
# container - An Azure::Blobs::Container instance.
|
|
111
|
+
# content - The content of this Blob.
|
|
112
|
+
# service - The Blobs service to perform external calls.
|
|
113
|
+
def initialize(name, container=nil, content=nil, service=Azure::Blobs)
|
|
114
|
+
@name = name
|
|
115
|
+
@container = container
|
|
116
|
+
@content = content
|
|
117
|
+
@properties = {}
|
|
118
|
+
@metadata = {}
|
|
119
|
+
@service = service
|
|
120
|
+
yield self if block_given?
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Public: The url of this blob.
|
|
124
|
+
#
|
|
125
|
+
# Returns a URI.
|
|
126
|
+
def url
|
|
127
|
+
Blobs::URI.blob(container.name, name)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# Public: Check equality between blobs. Two blobs are equal if they have
|
|
131
|
+
# the same name and belong to the same container.
|
|
132
|
+
#
|
|
133
|
+
# other - A Blob.
|
|
134
|
+
#
|
|
135
|
+
# Returns true|false.
|
|
136
|
+
def ==(other)
|
|
137
|
+
!container.nil? && container == other.container && name == other.name
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# Public: Delete this blob from the storage service. If the operation is
|
|
141
|
+
# unsuccessful this invalidates the blob.
|
|
142
|
+
#
|
|
143
|
+
# Returns true|false to indicate success.
|
|
144
|
+
def delete
|
|
145
|
+
@service.delete_blob(self)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# Public: Force a reload of this blob's metadata from the service.
|
|
149
|
+
#
|
|
150
|
+
# Returns the Hash of metadata.
|
|
151
|
+
def load_metadata!
|
|
152
|
+
@service.load_blob_metadata(self)
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# Public: Put the current blob's metadata into the storage service.
|
|
156
|
+
#
|
|
157
|
+
# Returns true|false to indicate success.
|
|
158
|
+
def save_metadata!
|
|
159
|
+
@service.save_blob_metadata(self)
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# Public: Extracts metadata from a hash containing HTTP headers (so
|
|
163
|
+
# "x-ms-meta-Name" => "Foo" is extracted as "Name" => "Foo"). This
|
|
164
|
+
# replaces the metadata of this container.
|
|
165
|
+
#
|
|
166
|
+
# hash - A hash of String => String with HTTP header values.
|
|
167
|
+
#
|
|
168
|
+
# Returns a Hash with the extracted metadata.
|
|
169
|
+
def extract_metadata(hash)
|
|
170
|
+
new_metadata = hash.each_with_object({}) do |(k,v), hash|
|
|
171
|
+
if key = k[/^x-ms-meta-(?<key>.*)?/, :key]
|
|
172
|
+
hash[key] = v
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
metadata.replace(new_metadata)
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
# Public: Put the current blob's properties into the storage service.
|
|
180
|
+
#
|
|
181
|
+
# headers - A Hash with user defined headers for this operation.
|
|
182
|
+
#
|
|
183
|
+
# Returns true|false to indicate success.
|
|
184
|
+
def save_properties!(headers={})
|
|
185
|
+
@service.save_blob_properties(self, headers)
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
# Public: Force a reload of this blob's properties from the server.
|
|
189
|
+
#
|
|
190
|
+
# headers - A Hash with user defined headers for this operation.
|
|
191
|
+
#
|
|
192
|
+
# Returns the Hash of properties.
|
|
193
|
+
def load_properties!(headers={})
|
|
194
|
+
@service.load_blob_properties(self, headers)
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# Public: Extracts properties from a hash containing HTTP headers. This
|
|
198
|
+
# replaces the properties of this container. Any headers that are
|
|
199
|
+
# contained in `PROPERTIES` are extracted.
|
|
200
|
+
#
|
|
201
|
+
# hash - A hash of String => String with HTTP header values.
|
|
202
|
+
#
|
|
203
|
+
# Returns a Hash with the extracted properties.
|
|
204
|
+
def extract_properties(hash)
|
|
205
|
+
new_properties = hash.select do |key, _|
|
|
206
|
+
PROPERTIES.include?(key)
|
|
207
|
+
end
|
|
208
|
+
new_properties.merge!("x-ms-lease-id" => lease_id) if lease_id
|
|
209
|
+
properties.replace(new_properties)
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
# Public: Generate a Shared Access Signature that can be used to provide
|
|
213
|
+
# anonymous access to this blob.
|
|
214
|
+
#
|
|
215
|
+
# permissions - A String with the permissions you want to grant on this
|
|
216
|
+
# blob. Might contain any of "r", "w", "d", or "l" *in this
|
|
217
|
+
# order*.
|
|
218
|
+
# to - Either a Date, Time or duration in seconds.
|
|
219
|
+
# from - A Date or Time (if `to` is a duration in seconds, then
|
|
220
|
+
# this is ignored).
|
|
221
|
+
# id - An identifier (optional).
|
|
222
|
+
# clock - Dependency on Time for calculations (optional).
|
|
223
|
+
# signature - Dependency on SharedAccessSignature (optional).
|
|
224
|
+
#
|
|
225
|
+
# Examples:
|
|
226
|
+
#
|
|
227
|
+
# # Valid for 10 minutes.
|
|
228
|
+
# blob.shared_access_signature("r", 10.minutes)
|
|
229
|
+
#
|
|
230
|
+
# # Read until Christmas 2012.
|
|
231
|
+
# blob.shared_access_signature("r", Date.new(2012, 12, 25))
|
|
232
|
+
#
|
|
233
|
+
# # Associate this signature with an access control policy:
|
|
234
|
+
# blob.shared_access_signature("r", 10.minutes, "policy-id")
|
|
235
|
+
#
|
|
236
|
+
# Returns a URL for this resource that includes the SAS.
|
|
237
|
+
def shared_access_signature(permissions, to, from=nil, id=nil, clock=Time, signature=SharedAccessSignature)
|
|
238
|
+
if to.respond_to?(:to_int)
|
|
239
|
+
id, to, from = from, clock.now.utc + to, clock.now.utc
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
signature.new(permissions, from, to, id).url(self)
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
# Public: String identifying which type of resource this is (used to
|
|
246
|
+
# generate shared access signatures).
|
|
247
|
+
#
|
|
248
|
+
# Returns the string "b".
|
|
249
|
+
def resource_type
|
|
250
|
+
"b"
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
# Public: Creates a snapshot of this Blob.
|
|
254
|
+
#
|
|
255
|
+
# metadata - A Hash representing blob metadata as :name => value. (optional)
|
|
256
|
+
#
|
|
257
|
+
# Returns an instance of Azure::Blobs::Snapshot.
|
|
258
|
+
def create_snapshot(metadata={})
|
|
259
|
+
Azure::Blobs.create_snapshot(self, metadata)
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
# Public: Get the lease_id from blob properties.
|
|
263
|
+
def lease_id
|
|
264
|
+
properties["x-ms-lease-id"]
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
class Snapshot < Blob
|
|
269
|
+
# Public: Return the datetime value for x-ms-snapshot property.
|
|
270
|
+
def id
|
|
271
|
+
properties["x-ms-snapshot"]
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
# Public: Delete this snapshot.
|
|
275
|
+
def delete
|
|
276
|
+
@service.delete_snapshot(self)
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
# Public: Acquire a Lease ID for this blob.
|
|
280
|
+
#
|
|
281
|
+
# http://msdn.microsoft.com/en-us/library/windowsazure/ee691972
|
|
282
|
+
def acquire_lease(service=Azure::Blobs)
|
|
283
|
+
service.lease(@blob, :acquire)
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
# Public: Renew Lease ID for this blob.
|
|
287
|
+
#
|
|
288
|
+
# http://msdn.microsoft.com/en-us/library/windowsazure/ee691972
|
|
289
|
+
def renew_lease(service=Azure::Blobs)
|
|
290
|
+
service.lease(@blob, :renew)
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
# Public: Release Lease ID for this blob.
|
|
294
|
+
#
|
|
295
|
+
# http://msdn.microsoft.com/en-us/library/windowsazure/ee691972
|
|
296
|
+
def release_lease(service=Azure::Blobs)
|
|
297
|
+
service.lease(@blob, :release)
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
# Public: Break Lease ID for this blob.
|
|
301
|
+
#
|
|
302
|
+
# http://msdn.microsoft.com/en-us/library/windowsazure/ee691972
|
|
303
|
+
def break_lease(service=Azure::Blobs)
|
|
304
|
+
service.lease(@blob, :break)
|
|
305
|
+
end
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
class BlockBlob < Blob
|
|
309
|
+
|
|
310
|
+
attr :content_type
|
|
311
|
+
|
|
312
|
+
# Public: Upload a file to this BlockBlob, override content if exist.
|
|
313
|
+
# Blob metadata and properties will be sent as well to preserve them.
|
|
314
|
+
#
|
|
315
|
+
# filename_or_stream - IO or String representing the resource on the filesystem.
|
|
316
|
+
# content_type - String representing the content-type of the uploaded blob. (optional)
|
|
317
|
+
# byte_partition - Optional. Integer representing the size of the chunks to be uploaded. (optional)
|
|
318
|
+
#
|
|
319
|
+
# Returns boolean indicating success.
|
|
320
|
+
def update(filename_or_stream, content_type=nil, byte_partition=nil, service=Azure::Blobs)
|
|
321
|
+
|
|
322
|
+
stream = filename_or_stream.is_a?(String) ? File.open(filename_or_stream) : filename_or_stream
|
|
323
|
+
|
|
324
|
+
@content_type = content_type ||= "application/octet-stream"
|
|
325
|
+
|
|
326
|
+
block_ids = service.update_block_blob_content(self, stream, byte_partition)
|
|
327
|
+
|
|
328
|
+
if block_ids.any? && service.put_block_list(self, block_ids)
|
|
329
|
+
stream.rewind
|
|
330
|
+
@content = stream.read
|
|
331
|
+
true
|
|
332
|
+
else
|
|
333
|
+
false
|
|
334
|
+
end
|
|
335
|
+
end
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
class PageBlob < Blob
|
|
339
|
+
# Public: Write Range of pages.
|
|
340
|
+
def update_range(start_byte, end_byte, stream)
|
|
341
|
+
if Azure::Blobs.update_page_range(self, start_byte, end_byte, stream)
|
|
342
|
+
@content = stream
|
|
343
|
+
true
|
|
344
|
+
else
|
|
345
|
+
false
|
|
346
|
+
end
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
# Public: Clear Range of pages.
|
|
350
|
+
def clear_range(start_byte, end_byte)
|
|
351
|
+
Azure::Blobs.clear_page_range(self, start_byte, end_byte)
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
# Public: Get Range of pages.
|
|
355
|
+
def get_range(start_byte=nil, end_byte=nil)
|
|
356
|
+
Azure::Blobs.get_page_range(self, start_byte, end_byte)
|
|
357
|
+
end
|
|
358
|
+
end
|
|
359
|
+
end
|
|
360
|
+
end
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
require "nokogiri"
|
|
2
|
+
require "uri"
|
|
3
|
+
require "azure/error"
|
|
4
|
+
require "azure/blobs"
|
|
5
|
+
require "azure/blobs/uri"
|
|
6
|
+
require "azure/blobs/shared_access_signature"
|
|
7
|
+
|
|
8
|
+
module Azure
|
|
9
|
+
module Blobs
|
|
10
|
+
class Container
|
|
11
|
+
include ErrorHandler
|
|
12
|
+
|
|
13
|
+
# Public: Indicates the both the information of the container and of its
|
|
14
|
+
# blobs is accessible by an anonymous request.
|
|
15
|
+
CONTAINER = :container
|
|
16
|
+
|
|
17
|
+
# Public: Indicates the blobs in this container can be accessed by an
|
|
18
|
+
# anonymous request, but not the information in the container.
|
|
19
|
+
BLOB = :blob
|
|
20
|
+
|
|
21
|
+
# Public: Indicates neither this container nor any of its blobs can be
|
|
22
|
+
# accessed by an anonymous request.
|
|
23
|
+
PRIVATE = :private
|
|
24
|
+
|
|
25
|
+
# Public: Get the name of the container.
|
|
26
|
+
attr :name
|
|
27
|
+
|
|
28
|
+
# Public: Get the URI of the container.
|
|
29
|
+
attr :url
|
|
30
|
+
|
|
31
|
+
# Public: Get/Set the User defined Metadata of the container.
|
|
32
|
+
attr :metadata
|
|
33
|
+
|
|
34
|
+
# Public: Get the Properties of the container.
|
|
35
|
+
attr :properties
|
|
36
|
+
|
|
37
|
+
# Public: Get the current container visibility for anonymous requests. See
|
|
38
|
+
# the x-ms-blob-public-access header on:
|
|
39
|
+
#
|
|
40
|
+
# http://msdn.microsoft.com/en-us/library/windowsazure/dd179468
|
|
41
|
+
attr_accessor :visibility
|
|
42
|
+
|
|
43
|
+
# Convert the value of a x-ms-blob-public-access header to one of our
|
|
44
|
+
# visibility constants.
|
|
45
|
+
#
|
|
46
|
+
# header_value - A string or nil.
|
|
47
|
+
#
|
|
48
|
+
# Returns either PRIVATE, BLOB, or CONTAINER.
|
|
49
|
+
def self.visibility(header_value)
|
|
50
|
+
case header_value
|
|
51
|
+
when "container", "true"
|
|
52
|
+
CONTAINER
|
|
53
|
+
when "blob"
|
|
54
|
+
BLOB
|
|
55
|
+
else
|
|
56
|
+
PRIVATE
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Public: Initialize a container from an XML node as returned from an API
|
|
61
|
+
# response.
|
|
62
|
+
#
|
|
63
|
+
# node - A Nokogiri::Node.
|
|
64
|
+
#
|
|
65
|
+
# Returns a Container.
|
|
66
|
+
def self.from_node(node)
|
|
67
|
+
name = (node % "Name").text
|
|
68
|
+
url = URI((node % "Url").text)
|
|
69
|
+
|
|
70
|
+
metadata = (node / "Metadata *").each_with_object({}) do |n, metadata|
|
|
71
|
+
metadata[n.name] = n.text
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
properties = (node / "Properties *").each_with_object({}) do |n, props|
|
|
75
|
+
props[n.name] = n.text
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
new(name, url) do |container|
|
|
79
|
+
container.properties.replace(properties)
|
|
80
|
+
container.metadata.replace(metadata)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Public: Initialize an invalid container from an erroneous response.
|
|
85
|
+
#
|
|
86
|
+
# error - An Azure::Error.
|
|
87
|
+
#
|
|
88
|
+
# Returns a Container.
|
|
89
|
+
def self.from_error(error)
|
|
90
|
+
container = new(nil, nil)
|
|
91
|
+
container.error = error
|
|
92
|
+
container
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Public: Initialize a Container.
|
|
96
|
+
#
|
|
97
|
+
# name - A String with the name of the Container.
|
|
98
|
+
# url - The URI that represents this container (optional).
|
|
99
|
+
# service - The Blobs service to perform external calls.
|
|
100
|
+
#
|
|
101
|
+
# Yields self (optional).
|
|
102
|
+
def initialize(name, url=Blobs::URI.container(name), service=Azure::Blobs)
|
|
103
|
+
@name = name
|
|
104
|
+
@url = url
|
|
105
|
+
@metadata = {}
|
|
106
|
+
@properties = {}
|
|
107
|
+
@service = service
|
|
108
|
+
yield self if block_given?
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Public: List the blobs inside this container.
|
|
112
|
+
#
|
|
113
|
+
# Returns an Array of Blobs.
|
|
114
|
+
def blobs
|
|
115
|
+
@service.blobs(self)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Public: Check equality between containers. Two containers are equal if
|
|
119
|
+
# they have equal names.
|
|
120
|
+
#
|
|
121
|
+
# other - A Container.
|
|
122
|
+
#
|
|
123
|
+
# Returns true|false.
|
|
124
|
+
def ==(other)
|
|
125
|
+
name == other.name
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Public: Force a reload of this containers metadata from the server.
|
|
129
|
+
#
|
|
130
|
+
# Returns the Hash of metadata.
|
|
131
|
+
def load_metadata!
|
|
132
|
+
@service.load_container_metadata(self)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# Public: Put the current container's metadata into the storage service.
|
|
136
|
+
#
|
|
137
|
+
# Returns true|false to indicate success.
|
|
138
|
+
def save_metadata!
|
|
139
|
+
@service.save_container_metadata(self)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# Public: Extracts metadata from a hash containing HTTP headers (so
|
|
143
|
+
# "x-ms-meta-Name" => "Foo" is extracted as "Name" => "Foo"). This
|
|
144
|
+
# replaces the metadata of this container.
|
|
145
|
+
#
|
|
146
|
+
# hash - A hash of String => String with HTTP header values.
|
|
147
|
+
#
|
|
148
|
+
# Returns a Hash with the extracted metadata.
|
|
149
|
+
def extract_metadata(hash)
|
|
150
|
+
new_metadata = hash.each_with_object({}) do |(k,v), hash|
|
|
151
|
+
if key = k[/^x-ms-meta-(?<key>.*)?/, :key]
|
|
152
|
+
hash[key] = v
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
metadata.replace(new_metadata)
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# Public: Generate a Shared Access Signature that can be used to provide
|
|
160
|
+
# anonymous access to this container.
|
|
161
|
+
#
|
|
162
|
+
# permissions - A String with the permissions you want to grant on this
|
|
163
|
+
# container. Might contain any of "r", "w", "d", or "l" *in
|
|
164
|
+
# this order*.
|
|
165
|
+
# to - Either a Date, Time or duration in seconds.
|
|
166
|
+
# from - A Date or Time (if `to` is a duration in seconds, then
|
|
167
|
+
# this is ignored).
|
|
168
|
+
# id - An identifier (optional).
|
|
169
|
+
# clock - Dependency on Time for calculations (optional).
|
|
170
|
+
# signature - Dependency on SharedAccessSignature (optional).
|
|
171
|
+
#
|
|
172
|
+
# Examples:
|
|
173
|
+
#
|
|
174
|
+
# # Valid for 10 minutes.
|
|
175
|
+
# container.shared_access_signature("r", 10.minutes)
|
|
176
|
+
#
|
|
177
|
+
# # Read until Christmas 2012.
|
|
178
|
+
# container.shared_access_signature("r", Date.new(2012, 12, 25))
|
|
179
|
+
#
|
|
180
|
+
# # Associate this signature with an access control policy:
|
|
181
|
+
# container.shared_access_signature("r", 10.minutes, "policy-id")
|
|
182
|
+
#
|
|
183
|
+
# Returns a URL for this resource that includes the SAS.
|
|
184
|
+
def shared_access_signature(permissions, to, from=nil, id=nil, clock=Time, signature=SharedAccessSignature)
|
|
185
|
+
if to.respond_to?(:to_int)
|
|
186
|
+
id, to, from = from, clock.now.utc + to, clock.now.utc
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
signature.new(permissions, from, to, id).url(self)
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# Public: Delete this container from the storage service. If the operation
|
|
193
|
+
# fails this returns false and sets self.error.
|
|
194
|
+
#
|
|
195
|
+
# Returns true|false to indicate success.
|
|
196
|
+
def delete
|
|
197
|
+
@service.delete_container(self)
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
# Public: String identifying which type of resource this is (used to
|
|
201
|
+
# generate shared access signatures).
|
|
202
|
+
#
|
|
203
|
+
# Returns the string "c".
|
|
204
|
+
def resource_type
|
|
205
|
+
"c"
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
end
|