azure-armrest 0.7.5 → 0.8.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5eafec5e5c9b51f1e01cd36f55872192579cf838
4
- data.tar.gz: 80dfaca5f2bec22dcdea5567295248e3a12b254f
3
+ metadata.gz: 8132014956246e577b66ccaf5a59e002e1dc06d3
4
+ data.tar.gz: f15ad3108839654399c954bb0f4460499de319cd
5
5
  SHA512:
6
- metadata.gz: 1f4dcb334ccb37db304d216ffeae044944724f1b517e317a1ea3d4393840203af5b665640806e07f8a5564fa723d66a0c4b3eb7bb802d66de1b6a85d2f0cefa8
7
- data.tar.gz: d0d956239b40e8ca6e59cecfa47650c1334c3b79dae481bef71d8a0485d9e14ada0cce04dba882ad045ef9acc3ddbbc9e8e10d6f52d3b04bb9f6dd721431592d
6
+ metadata.gz: 4ca343728c62c77096e320d04ea0bfdeb0e6d9ce3aadbc0ea53935053335d1b20089004591915cf031fa380bd16009f89e7acdea0db4cb08b8098274d7dc3276
7
+ data.tar.gz: b0185801ee3a2c6cf1079f5f8040ca143402109659b991504b40d2a6e06fa294452163086c00094fdaddca1553738af3278ac0464115f502652894684901c6af
data/CHANGES CHANGED
@@ -1,3 +1,15 @@
1
+ = 0.8.0 - 20-Jul-2017
2
+ * The StorageAccount#create_blob and StorageAccount#create_blob_snapshot methods
3
+ were heavily revamped and now return a ResponseHeaders object.
4
+ * Added support for storage file services to the Storage model, so you can
5
+ now create, delete or query files or directories on storage accounts.
6
+ * Added the list_all instance method to the VirtualMachineImageService class.
7
+ Thanks go to Tyler Gregory for the patch.
8
+ * Added the ArmestService#list_locations method. This returns an array of
9
+ Location objects. The ArmrestService#locations method still returns just
10
+ an array of strings, but is now deprecated.
11
+ * The StorageAccount#all_blobs method now accepts an options argument.
12
+
1
13
  = 0.7.5 - 27-Jun-2017
2
14
  * Added the ContainerService service class.
3
15
  * Added the StorageAccount#access_key accessor. If set, this is now used as
@@ -77,17 +77,27 @@ module Azure
77
77
  # +provider+. If you do not specify a provider, then the locations for
78
78
  # all providers will be returned.
79
79
  #
80
- # If you need individual details on a per-provider basis, use the
81
- # provider_info method instead.
82
- #--
80
+ # If you need individual details on a per-provider basis, use the methods
81
+ # of the ResourceProviderService instead.
82
+ #
83
+ # Deprecated.
83
84
  #
84
85
  def locations(provider = nil)
85
86
  list = configuration.providers
86
87
  list = list.select { |rp| rp.namespace.casecmp(provider) == 0 } if provider
87
-
88
88
  list.collect { |rp| rp.resource_types.map(&:locations) }.flatten.uniq.sort
89
89
  end
90
90
 
91
+ deprecate :locations, :list_locations, 2019, 1
92
+
93
+ # Returns a list of Location objects for the current subscription.
94
+ #
95
+ def list_locations
96
+ url = url_with_api_version(configuration.api_version, base_url, 'locations')
97
+ response = rest_get(url)
98
+ Azure::Armrest::ArmrestCollection.create_from_response(response, Location)
99
+ end
100
+
91
101
  # Returns a list of subscriptions for the current tenant.
92
102
  def list_subscriptions
93
103
  Azure::Armrest::SubscriptionService.new(configuration).list
@@ -191,6 +191,7 @@ module Azure
191
191
  class Container < BaseModel; end
192
192
  class Event < BaseModel; end
193
193
  class ImageVersion < BaseModel; end
194
+ class Location < BaseModel; end
194
195
  class Offer < BaseModel; end
195
196
  class Publisher < BaseModel; end
196
197
  class Resource < BaseModel; end
@@ -20,6 +20,10 @@ module Azure
20
20
  class Table < BaseModel; end
21
21
  class TableData < BaseModel; end
22
22
 
23
+ # Classes used to wrap file shares
24
+ class ShareDirectory < BaseModel; end
25
+ class ShareFile < BaseModel; end
26
+
23
27
  # The version string used in headers sent as part any internal http
24
28
  # request. The default is 2016-05-31.
25
29
  attr_accessor :storage_api_version
@@ -50,7 +54,7 @@ module Azure
50
54
  def tables(key = access_key)
51
55
  raise ArgumentError, "No access key specified" unless key
52
56
  response = table_response(key, nil, "Tables")
53
- JSON.parse(response.body)['value'].map{ |t| Table.new(t) }
57
+ JSON.parse(response.body)['value'].map { |t| Table.new(t) }
54
58
  end
55
59
 
56
60
  # Return information about a single table for the given storage
@@ -119,6 +123,280 @@ module Azure
119
123
  data
120
124
  end
121
125
 
126
+ ### Files and Directories
127
+
128
+ # Create a new directory under the specified +share+ or parent directory.
129
+ #
130
+ # The only supported option at this time is a "timeout" option.
131
+ #
132
+ def create_directory(share, directory, key = access_key, options = {})
133
+ raise ArgumentError, "No access key specified" unless key
134
+
135
+ query = {:restype => 'directory'}.merge(options).to_query
136
+
137
+ response = file_response(key, query, 'put', '', File.join(share, directory))
138
+
139
+ Azure::Armrest::ResponseHeaders.new(response.headers).tap do |rh|
140
+ rh.response_code = response.code
141
+ end
142
+ end
143
+
144
+ # Delete the specified +share+ or parent directory.
145
+ #
146
+ # The only supported option at this time is a "timeout" option.
147
+ #
148
+ def delete_directory(share, directory, key = access_key, options = {})
149
+ raise ArgumentError, "No access key specified" unless key
150
+
151
+ query = {:restype => 'directory'}.merge(options).to_query
152
+
153
+ response = file_response(key, query, 'delete', '', File.join(share, directory))
154
+
155
+ Azure::Armrest::ResponseHeaders.new(response.headers).tap do |rh|
156
+ rh.response_code = response.code
157
+ end
158
+ end
159
+
160
+ # Get properties for the specified +share+ or parent directory.
161
+ #
162
+ # The only supported option at this time is a "timeout" option.
163
+ #
164
+ def directory_properties(share, directory, key = access_key, options = {})
165
+ raise ArgumentError, "No access key specified" unless key
166
+
167
+ query = {:restype => 'directory'}.merge(options).to_query
168
+
169
+ response = file_response(key, query, 'get', '', File.join(share, directory))
170
+
171
+ ShareDirectory.new(response.headers)
172
+ end
173
+
174
+ # Get metadata for the specified +share+ or parent directory.
175
+ #
176
+ # The only supported option at this time is a "timeout" option.
177
+ #
178
+ def directory_metadata(share, directory, key = access_key, options = {})
179
+ raise ArgumentError, "No access key specified" unless key
180
+
181
+ query = {:restype => 'directory', :comp => 'metadata'}.merge(options).to_query
182
+
183
+ response = file_response(key, query, 'head', '', File.join(share, directory))
184
+
185
+ ShareDirectory.new(response.headers)
186
+ end
187
+
188
+ # Returns a list of files for the specified file-share. You may also
189
+ # optionally specify a +directory+ in "share/directory" format.
190
+ #
191
+ # You may specify multiple +options+ to limit the result set. The
192
+ # possible options are:
193
+ #
194
+ # * prefix
195
+ # * marker
196
+ # * maxresults
197
+ # * timeout
198
+ #
199
+ def files(share, key = access_key, options = {})
200
+ raise ArgumentError, "No access key specified" unless key
201
+
202
+ query = {:restype => 'directory', :comp => 'list'}.merge(options).to_query
203
+
204
+ response = file_response(key, query, 'get', nil, share)
205
+
206
+ doc = Nokogiri::XML(response.body)
207
+ results = []
208
+
209
+ doc.xpath('//EnumerationResults/Entries').each do |element|
210
+ element.xpath('//Directory').each do |dir|
211
+ results << ShareDirectory.new(Hash.from_xml(dir.to_s)['Directory'])
212
+ end
213
+ element.xpath('//File').each do |file|
214
+ results << ShareFile.new(Hash.from_xml(file.to_s)['File'])
215
+ end
216
+ end
217
+
218
+ results.concat(next_marker_results(doc, :files, key, options))
219
+
220
+ results
221
+ end
222
+
223
+ # Returns the raw contents of the specified file.
224
+ #
225
+ # The only supported option at this time is a "timeout" option.
226
+ #
227
+ def file_content(share, file, key = access_key, options = {})
228
+ raise ArgumentError, "No access key specified" unless key
229
+
230
+ query = options.to_query
231
+
232
+ response = file_response(key, query, 'get', '', File.join(share, file))
233
+ response.body
234
+ end
235
+
236
+ # Returns the raw contents of the specified file.
237
+ #
238
+ # The only supported option at this time is a "timeout" option.
239
+ #
240
+ def file_properties(share, file, key = access_key, options = {})
241
+ raise ArgumentError, "No access key specified" unless key
242
+
243
+ query = options.to_query
244
+
245
+ response = file_response(key, query, 'head', '', File.join(share, file))
246
+
247
+ Azure::Armrest::ResponseHeaders.new(response.headers).tap do |rh|
248
+ rh.response_code = response.code
249
+ end
250
+ end
251
+
252
+ # Create the specified share file. You may specify any of the following
253
+ # options:
254
+ #
255
+ # * cache_control
256
+ # * content_disposition
257
+ # * content_length (default: 0)
258
+ # * content_encoding
259
+ # * content_language
260
+ # * content_md5
261
+ # * content_type (default: application/octet-stream)
262
+ # * meta_name
263
+ # * timeout
264
+ # * version
265
+ #
266
+ # Note that this does not set the content of the file, it only creates
267
+ # in the file share.
268
+ #
269
+ def create_file(share, file, key = access_key, options = {})
270
+ raise ArgumentError, "No access key specified" unless key
271
+
272
+ timeout = options.delete(:timeout) # Part of request
273
+
274
+ url = File.join(properties.primary_endpoints.file, share, file)
275
+ url += "?timeout=#{timeout}" if timeout
276
+
277
+ hash = options.transform_keys.each { |okey| 'x-ms-' + okey.to_s.tr('_', '-') }
278
+
279
+ hash['verb'] = 'PUT'
280
+
281
+ # Mandatory and/or sane defaults
282
+ hash['x-ms-type'] = 'file'
283
+ hash['x-ms-content-length'] ||= 0
284
+ hash['x-ms-content-type'] ||= 'application/octet-stream'
285
+
286
+ headers = build_headers(url, key, :file, hash)
287
+
288
+ response = ArmrestService.send(
289
+ :rest_put,
290
+ :url => url,
291
+ :payload => '',
292
+ :headers => headers,
293
+ :proxy => proxy,
294
+ :ssl_version => ssl_version,
295
+ :ssl_verify => ssl_verify
296
+ )
297
+
298
+ Azure::Armrest::ResponseHeaders.new(response.headers).tap do |rh|
299
+ rh.response_code = response.code
300
+ end
301
+ end
302
+
303
+ # Delete the specified share file.
304
+ #
305
+ # The only supported option at this time is a "timeout" option.
306
+ #
307
+ def delete_file(share, file, key = access_key, options = {})
308
+ raise ArgumentError, "No access key specified" unless key
309
+
310
+ query = options.to_query
311
+
312
+ response = file_response(key, query, 'delete', '', File.join(share, file))
313
+
314
+ Azure::Armrest::ResponseHeaders.new(response.headers).tap do |rh|
315
+ rh.response_code = response.code
316
+ end
317
+ end
318
+
319
+ # Copy a +src_file+ to a destination +dst_file+ within the same storage account.
320
+ #
321
+ def copy_file(src_container, src_file, dst_container = src_container, dst_file = nil, key = access_key)
322
+ raise ArgumentError, "No access key specified" unless key
323
+
324
+ dst_file ||= File.basename(src_blob)
325
+
326
+ dst_url = File.join(properties.primary_endpoints.file, dst_container, dst_file)
327
+ src_url = File.join(properties.primary_endpoints.file, src_container, src_file)
328
+
329
+ options = {'x-ms-copy-source' => src_url, :verb => 'PUT'}
330
+
331
+ headers = build_headers(dst_url, key, :file, options)
332
+
333
+ response = ArmrestService.send(
334
+ :rest_put,
335
+ :url => dst_url,
336
+ :payload => '',
337
+ :headers => headers,
338
+ :proxy => proxy,
339
+ :ssl_version => ssl_version,
340
+ :ssl_verify => ssl_verify
341
+ )
342
+
343
+ Azure::Armrest::ResponseHeaders.new(response.headers).tap do |rh|
344
+ rh.response_code = response.code
345
+ end
346
+ end
347
+
348
+ # Add content to +file+ on +share+. The +options+ hash supports
349
+ # three options, :content, :timeout and :write.
350
+ #
351
+ # The :content option is just a string, i.e. the content you want
352
+ # to add to the file. Azure allows you to add a maximum of 4mb worth
353
+ # of content per request.
354
+ #
355
+ # The :timeout option is nil by default. The :write option defaults to
356
+ # 'update'. If you want to clear a file, set it to 'clear'.
357
+ #
358
+ def add_file_content(share, file, key = access_key, options = {})
359
+ raise ArgumentError, "No access key specified" unless key
360
+
361
+ timeout = options.delete(:timeout)
362
+ content = options.delete(:content)
363
+
364
+ url = File.join(properties.primary_endpoints.file, share, file) + "?comp=range"
365
+ url += "&timeout=#{timeout}" if timeout
366
+
367
+ hash = options.transform_keys.each { |okey| 'x-ms-' + okey.to_s.tr('_', '-') }
368
+
369
+ hash['verb'] = 'PUT'
370
+ hash['x-ms-write'] ||= 'update'
371
+
372
+ if hash['x-ms-write'] == 'clear'
373
+ hash['content-length'] = 0
374
+ hash['x-ms-range'] = "bytes=0-"
375
+ else
376
+ range = 0..(content.size - 1)
377
+ hash['content-length'] = content.size
378
+ hash['x-ms-range'] = "bytes=#{range.min}-#{range.max}"
379
+ end
380
+
381
+ headers = build_headers(url, key, :file, hash)
382
+
383
+ response = ArmrestService.send(
384
+ :rest_put,
385
+ :url => url,
386
+ :payload => content,
387
+ :headers => headers,
388
+ :proxy => proxy,
389
+ :ssl_version => ssl_version,
390
+ :ssl_verify => ssl_verify
391
+ )
392
+
393
+ Azure::Armrest::ResponseHeaders.new(response.headers).tap do |rh|
394
+ rh.response_code = response.code
395
+ end
396
+ end
397
+
398
+ ### Containers
399
+
122
400
  # Return a list of container names for the given storage account +key+.
123
401
  # If no key is provided, it is assumed that the StorageAccount object
124
402
  # includes the access_key property.
@@ -237,9 +515,7 @@ module Azure
237
515
 
238
516
  url = File.join(properties.primary_endpoints.blob, container, blob) + "?comp=properties"
239
517
 
240
- hash = options.transform_keys do |okey|
241
- "x-ms-blob-" + okey.to_s.tr('_', '-')
242
- end
518
+ hash = options.transform_keys { |okey| "x-ms-blob-" + okey.to_s.tr('_', '-') }
243
519
 
244
520
  hash['verb'] = 'PUT'
245
521
 
@@ -306,9 +582,11 @@ module Azure
306
582
  results.concat(next_marker_results(doc, :blobs, container, key, options))
307
583
  end
308
584
 
309
- # Returns an array of all blobs for all containers.
585
+ # Returns an array of all blobs for all containers. The +options+ hash
586
+ # may contain the same arguments that a call to StorageAccount#blobs
587
+ # would accept.
310
588
  #
311
- def all_blobs(key = access_key, max_threads = 10)
589
+ def all_blobs(key = access_key, max_threads = 10, options = {})
312
590
  raise ArgumentError, "No access key specified" unless key
313
591
 
314
592
  array = []
@@ -316,7 +594,7 @@ module Azure
316
594
 
317
595
  Parallel.each(containers(key), :in_threads => max_threads) do |container|
318
596
  begin
319
- mutex.synchronize { array.concat(blobs(container.name, key)) }
597
+ mutex.synchronize { array.concat(blobs(container.name, key, options)) }
320
598
  rescue Errno::ECONNREFUSED, Azure::Armrest::TimeoutException => err
321
599
  msg "Unable to gather blob information for #{container.name}: #{err}"
322
600
  log('warn', msg)
@@ -404,7 +682,8 @@ module Azure
404
682
  blob
405
683
  end
406
684
 
407
- # Delete the given +blob+ found in +container+.
685
+ # Delete the given +blob+ found in +container+. Pass a :date option
686
+ # if you wish to delete a snapshot.
408
687
  #
409
688
  def delete_blob(container, blob, key = access_key, options = {})
410
689
  raise ArgumentError, "No access key specified" unless key
@@ -431,43 +710,113 @@ module Azure
431
710
 
432
711
  # Create new blob for a container.
433
712
  #
434
- # The +data+ parameter is a hash that contains the blob's information:
713
+ # The options parameter is a hash that contains information used
714
+ # when creating the blob:
435
715
  #
436
- # data['x-ms-blob-type']
437
- # # - Required. Specifies the type of blob to create: block, page or append.
716
+ # * type - "BlockBlob", "PageBlob" or "AppendBlob". Mandatory.
438
717
  #
439
- # data['x-ms-blob-content-encoding']
440
- # # - Optional. Set the blob’s content encoding.
441
- # ...
442
- def create_blob(container, blob, data, key = access_key)
718
+ # * content_disposition
719
+ # * content_encoding
720
+ # * content_language
721
+ # * content_md5
722
+ # * content_type
723
+ # * cache_control
724
+ # * lease_id
725
+ # * payload (block blobs only)
726
+ # * sequence_number (page blobs only)
727
+ # * timeout (part of the request)
728
+ #
729
+ # Returns a ResponseHeaders object since this method is asynchronous.
730
+ #
731
+ def create_blob(container, blob, key = access_key, options = {})
443
732
  raise ArgumentError, "No access key specified" unless key
444
733
 
734
+ timeout = options.delete(:timeout)
735
+ payload = options.delete(:payload) || ''
736
+
445
737
  url = File.join(properties.primary_endpoints.blob, container, blob)
738
+ url += "&timeout=#{timeout}" if timeout
446
739
 
447
- options = {:verb => 'PUT'}
448
- options = options.merge(data)
449
- headers = build_headers(url, key, :blob, options)
740
+ hash = options.transform_keys do |okey|
741
+ if okey.to_s =~ /^if/i
742
+ okey.to_s.tr('_', '-')
743
+ elsif %w[date meta_name lease_id version].include?(okey.to_s)
744
+ 'x-ms-' + okey.to_s.tr('_', '-')
745
+ else
746
+ 'x-ms-blob-' + okey.to_s.tr('_', '-')
747
+ end
748
+ end
749
+
750
+ unless hash['x-ms-blob-type']
751
+ raise ArgumentError, "The :type option must be specified"
752
+ end
753
+
754
+ hash['x-ms-date'] ||= Time.now.httpdate
755
+ hash['x-ms-version'] ||= @storage_api_version
756
+ hash['verb'] = 'PUT'
757
+
758
+ # Content length must be 0 (blank) for Page or Append blobs
759
+ if %w[pageblob appendblob].include?(hash['x-ms-blob-type'].downcase)
760
+ hash['content-length'] = ''
761
+ else
762
+ hash['content-length'] ||= hash['x-ms-blob-content-length']
763
+ end
764
+
765
+ # Override the default empty string
766
+ hash['content-type'] ||= hash['x-ms-blob-content-type'] || 'application/octet-stream'
767
+
768
+ headers = build_headers(url, key, :blob, hash)
450
769
 
451
770
  response = ArmrestService.send(
452
771
  :rest_put,
453
772
  :url => url,
454
- :payload => '',
773
+ :payload => payload,
455
774
  :headers => headers,
456
775
  :proxy => proxy,
457
776
  :ssl_version => ssl_version,
458
777
  :ssl_verify => ssl_verify
459
778
  )
460
779
 
461
- Blob.new(response.headers)
780
+ resp_headers = Azure::Armrest::ResponseHeaders.new(response.headers)
781
+ resp_headers.response_code = response.code
782
+
783
+ resp_headers
462
784
  end
463
785
 
464
- def create_blob_snapshot(container, blob, key = access_key)
786
+ # Create a read-only snapshot of a blob.
787
+ #
788
+ # Possible options are:
789
+ #
790
+ # * meta_name
791
+ # * lease_id
792
+ # * client_request_id
793
+ # * if_modified_since
794
+ # * if_unmodified_since
795
+ # * if_match
796
+ # * if_none_match
797
+ # * timeout
798
+ #
799
+ # Returns a ResponseHeaders object since this is an asynchronous method.
800
+ #
801
+ def create_blob_snapshot(container, blob, key = access_key, options = {})
465
802
  raise ArgumentError, "No access key specified" unless key
466
803
 
467
- url = File.join(properties.primary_endpoints.blob, container, blob)
468
- url += "?comp=snapshot"
804
+ timeout = options.delete(:timeout) # Part of request
805
+
806
+ url = File.join(properties.primary_endpoints.blob, container, blob) + "?comp=snapshot"
807
+ url += "&timeout=#{timeout}" if timeout
808
+
809
+ hash = options.transform_keys do |okey|
810
+ if okey.to_s =~ /^if/i
811
+ okey.to_s.tr('_', '-')
812
+ else
813
+ 'x-ms-blob-' + okey.to_s.tr('_', '-')
814
+ end
815
+ end
469
816
 
470
- headers = build_headers(url, key, :blob, :verb => 'PUT')
817
+ hash['verb'] = 'PUT'
818
+
819
+ headers = build_headers(url, key, :blob, hash)
471
820
 
472
821
  response = ArmrestService.send(
473
822
  :rest_put,
@@ -479,11 +828,10 @@ module Azure
479
828
  :ssl_verify => ssl_verify
480
829
  )
481
830
 
482
- BlobSnapshot.new(
483
- 'name' => blob,
484
- 'last_modified' => response.headers.fetch(:last_modified),
485
- 'snapshot' => response.headers.fetch(:x_ms_snapshot)
486
- )
831
+ headers = Azure::Armrest::ResponseHeaders.new(response.headers)
832
+ headers.response_code = response.code
833
+
834
+ headers
487
835
  end
488
836
 
489
837
  # Get the contents of the given +blob+ found in +container+ using the
@@ -612,6 +960,31 @@ module Azure
612
960
  )
613
961
  end
614
962
 
963
+ # Using the file primary endpoint as a base, join any arguments to the
964
+ # the url and submit an http request.
965
+ #
966
+ def file_response(key, query, request_type = 'get', payload = '', *args)
967
+ url = File.join(properties.primary_endpoints.file, *args)
968
+ url += "?#{query}" if query && !query.empty?
969
+ request_method = "rest_#{request_type}".to_sym
970
+
971
+ headers = build_headers(url, key, :file, :verb => request_type.to_s.upcase)
972
+
973
+ params = {
974
+ :url => url,
975
+ :headers => headers,
976
+ :proxy => proxy,
977
+ :ssl_version => ssl_version,
978
+ :ssl_verify => ssl_verify,
979
+ }
980
+
981
+ if %w[put post].include?(request_type.to_s.downcase)
982
+ params[:payload] = payload
983
+ end
984
+
985
+ ArmrestService.send(request_method, params)
986
+ end
987
+
615
988
  # Using the blob primary endpoint as a base, join any arguments to the
616
989
  # the url and submit an http request.
617
990
  def table_response(key, query = nil, *args)
@@ -644,8 +1017,10 @@ module Azure
644
1017
  # RestClient will set the Content-Type to application/x-www-form-urlencoded.
645
1018
  # We must override this setting or the request will fail in some cases.
646
1019
 
1020
+ content_type = additional_headers['content-type'] || ''
1021
+
647
1022
  headers = {
648
- 'content-type' => '',
1023
+ 'content-type' => content_type,
649
1024
  'x-ms-date' => Time.now.httpdate,
650
1025
  'x-ms-version' => @storage_api_version,
651
1026
  'auth_string' => true
@@ -6,7 +6,7 @@ module Azure
6
6
  module Storage
7
7
  # Base class for managing images.
8
8
  class ImageService < ResourceGroupBasedService
9
- # Create and return a new DiskService instance.
9
+ # Create and return a new ImageService instance.
10
10
  #
11
11
  def initialize(configuration, options = {})
12
12
  super(configuration, 'images', 'Microsoft.Compute', options)
@@ -1,6 +1,6 @@
1
1
  module Azure
2
2
  module Armrest
3
3
  # The version of the azure-armrest library.
4
- VERSION = '0.7.5'.freeze
4
+ VERSION = '0.8.0'.freeze
5
5
  end
6
6
  end
@@ -22,6 +22,35 @@ module Azure
22
22
  @publisher = options[:publisher]
23
23
  end
24
24
 
25
+ # Return a list of all VM image offers from the given +location+.
26
+ #
27
+ # Example:
28
+ #
29
+ # vmis.list_all('eastus')
30
+ #
31
+ def list_all(location = @location)
32
+ raise ArgumentError, "No location specified" unless location
33
+
34
+ images = []
35
+ publishers(location).each do |publisher|
36
+ offers(location, publisher.name).each do |offer|
37
+ skus(offer.name, location, publisher.name).each do |sku|
38
+ versions(sku.name, offer.name, location, publisher.name).each do |version|
39
+ images << Azure::Armrest::VirtualMachineImage.new(
40
+ :location => version.location,
41
+ :publisher => publisher.name,
42
+ :offer => offer.name,
43
+ :sku => sku.name,
44
+ :version => version.name,
45
+ :id => "#{publisher.name}:#{offer.name}:#{sku.name}:#{version.name}"
46
+ )
47
+ end
48
+ end
49
+ end
50
+ end
51
+ images
52
+ end
53
+
25
54
  # Return a list of VM image offers from the given +publisher+ and +location+.
26
55
  #
27
56
  # Example:
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: azure-armrest
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.5
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel J. Berger
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2017-06-27 00:00:00.000000000 Z
14
+ date: 2017-07-20 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: json
@@ -300,7 +300,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
300
300
  version: '0'
301
301
  requirements: []
302
302
  rubyforge_project:
303
- rubygems_version: 2.5.2
303
+ rubygems_version: 2.6.12
304
304
  signing_key:
305
305
  specification_version: 4
306
306
  summary: An interface for ARM/JSON Azure REST API