azure-armrest 0.8.4 → 0.8.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9addd4499d546f9fb5eb12b5e454046709164836
4
- data.tar.gz: 3ccf69833fe525244581ed5e68b4e73503044bfd
3
+ metadata.gz: 271d67cb70166d8d00b30c234d1ecb6f26cfaaf5
4
+ data.tar.gz: adfdb6724dd8ca45b8314ba48537ff2ad229f469
5
5
  SHA512:
6
- metadata.gz: 63a3a2109b5d66e4de0f381d03d283bfdeef576c35bdf5b367c1fb473a67ea1bd36a21e97ee1d195222c1d3eab0812038dc48797cebb800fc8163d20f137d632
7
- data.tar.gz: 2e304ffabb9f08ca194fc5baed83a567acf007e2de0f2543e09a7886367b8e10b59abfe14519810d2c85def97675bb1fa55c4b022b15f6d252f7d59a684c8dc2
6
+ metadata.gz: ae90f2ed141868131b93df713ddae8e54b559ffd503da223fc3d6a9daad01cb3bf1b14d0c87e6ffc54156933407b93268d964dadf65b5a22cadfa1831a755ced
7
+ data.tar.gz: 4a0da229be85bd145421d215cfa064e7cebf745fe754b058f9d2a54fc2c0140ffff3492854877168e6b815b304dad0aa72c8588582e6dd990e98f7775e1981ff
data/.rubocop_local.yml CHANGED
@@ -0,0 +1,3 @@
1
+ Style/MethodCallWithArgsParentheses:
2
+ IgnoredMethods:
3
+ - attr_from_hash
data/CHANGES CHANGED
@@ -1,3 +1,6 @@
1
+ = 0.8.5 - 10-Oct-2017
2
+ * Backported the light model changes from 0.9.0.
3
+
1
4
  = 0.8.4 - 2-Oct-2017
2
5
  * Logging bug fix in StorageAccount#all_blobs method.
3
6
  * Modified the StorageAccountService#list_all_private_image method. It now
@@ -16,9 +16,9 @@ module Azure
16
16
  # using +klass+ to generate the list elements. In addition, both the
17
17
  # response headers and continuation token are set.
18
18
  #
19
- def create_from_response(response, klass = nil)
19
+ def create_from_response(response, klass = nil, skip_accessors_definition = false)
20
20
  json_response = JSON.parse(response)
21
- array = new(json_response['value'].map { |hash| klass.new(hash) })
21
+ array = new(json_response['value'].map { |hash| klass.new(hash, skip_accessors_definition) })
22
22
 
23
23
  array.response_code = response.code
24
24
  array.response_headers = response.headers
@@ -357,13 +357,13 @@ module Azure
357
357
  end
358
358
 
359
359
  # Make additional calls and concatenate the results if a continuation URL is found.
360
- def get_all_results(response)
361
- results = Azure::Armrest::ArmrestCollection.create_from_response(response, model_class)
360
+ def get_all_results(response, skip_accessors_definition = false)
361
+ results = Azure::Armrest::ArmrestCollection.create_from_response(response, model_class, skip_accessors_definition)
362
362
  nextlink = results.next_link
363
363
 
364
364
  while nextlink
365
365
  response = rest_get_without_encoding(nextlink)
366
- more = Azure::Armrest::ArmrestCollection.create_from_response(response, model_class)
366
+ more = Azure::Armrest::ArmrestCollection.create_from_response(response, model_class, skip_accessors_definition)
367
367
  results.concat(more)
368
368
  nextlink = more.next_link
369
369
  end
@@ -23,6 +23,58 @@ module Azure
23
23
 
24
24
  attr_hash :tags
25
25
 
26
+ # Defines attr_reader methods for the given set of attributes and
27
+ # expected hash key. Used to define methods that can be used internally
28
+ # that avoid needing to use methods defined from
29
+ # `add_accessor_methods`/`__setobj__`
30
+ #
31
+ # Example:
32
+ # class Vm < Azure::ArmRest::BaseModel
33
+ # attr_from_hash :name => :Name
34
+ # end
35
+ #
36
+ # json_string = {'name' => 'Deathstar'}
37
+ #
38
+ # vm = Vm.new(json_string)
39
+ # vm.name_from_hash
40
+ # #=> "Deathstar"
41
+ #
42
+ # # If the attr_from_hash can also support multiple attrs in a single
43
+ # # call, and nested params
44
+ #
45
+ # class Host < Azure::ArmRest::BaseModel
46
+ # attr_from_hash :name => :Name,
47
+ # :address => [:Properties, :ipAddress],
48
+ # end
49
+ #
50
+ # json_string = {'name' => 'Hoth', :Properties => {:ipAddress => '123.123.123.123'}}
51
+ #
52
+ # host = Host.new(json_string)
53
+ # host.name_from_hash
54
+ # #=> "Hoth"
55
+ # host.address_from_hash
56
+ # #=> "123.123.123.123"
57
+ #
58
+ def self.attr_from_hash(attrs = {})
59
+ file, line, _ = caller.first.split(":")
60
+ attrs.each do |attr_name, keys|
61
+ keys = Array(keys)
62
+ first_key = keys.shift
63
+ method_def = [
64
+ "def #{attr_name}_from_hash",
65
+ " return @#{attr_name}_from_hash if defined?(@#{attr_name}_from_hash)",
66
+ " @#{attr_name}_from_hash = __getobj__[:#{first_key}] || __getobj__[\"#{first_key}\"]",
67
+ "end"
68
+ ]
69
+ keys.each do |hash_key|
70
+ method_def.insert(-2, " @#{attr_name}_from_hash = @#{attr_name}_from_hash[:#{hash_key}] || @#{attr_name}_from_hash[\"#{hash_key}\"]")
71
+ end
72
+ class_eval(method_def.join("; "), file, line.to_i)
73
+ end
74
+ end
75
+
76
+ private_class_method :attr_from_hash
77
+
26
78
  attr_accessor :response_headers
27
79
  attr_accessor :response_code
28
80
 
@@ -48,7 +100,7 @@ module Azure
48
100
  # # Or you can get back the original JSON if necessary.
49
101
  # person.to_json # => Returns original JSON
50
102
  #
51
- def initialize(json)
103
+ def initialize(json, skip_accessors_definition = false)
52
104
  # Find the exclusion list for the model of next level (@embed_model)
53
105
  # '#' is the separator between levels. Remove attributes
54
106
  # before the first separator.
@@ -63,15 +115,24 @@ module Azure
63
115
  @json = json
64
116
  end
65
117
 
66
- __setobj__(@hash.dup)
118
+ @hashobj = @hash.dup
119
+ __setobj__ unless skip_accessors_definition
67
120
  end
68
121
 
69
122
  def resource_group
70
- @resource_group ||= id[/resourcegroups\/(.*?[^\/]+)?/i, 1] rescue nil
123
+ @resource_group ||= begin
124
+ id_from_hash[/resourcegroups\/(.*?[^\/]+)?/i, 1]
125
+ rescue
126
+ nil
127
+ end
71
128
  end
72
129
 
73
130
  def subscription_id
74
- @subscription_id ||= id[/subscriptions\/(.*?[^\/]+)?/i, 1] rescue nil
131
+ @subscription_id ||= begin
132
+ id_from_hash[/subscriptions\/(.*?[^\/]+)?/i, 1]
133
+ rescue
134
+ nil
135
+ end
75
136
  end
76
137
 
77
138
  attr_writer :resource_group
@@ -148,21 +209,29 @@ module Azure
148
209
  @hashobj
149
210
  end
150
211
 
212
+ # Do not use this method directly.
213
+ #
214
+ # Will only attempt to fetch the id from the @hashobj once, so even it it
215
+ # is nil, it will cache that value, and return that on subsequent calls.
216
+ def id_from_hash
217
+ return @id_from_hash if defined?(@id_from_hash)
218
+ @id_from_hash = __getobj__[:id] || __getobj__["id"]
219
+ end
220
+
151
221
  # Create snake_case accessor methods for all hash attributes
152
222
  # Use _alias if an accessor conflicts with existing methods
153
- def __setobj__(obj)
154
- @hashobj = obj
223
+ def __setobj__
155
224
  excl_list = self.class.send(:excl_list)
156
- obj.each do |key, value|
225
+ @hashobj.each do |key, value|
157
226
  snake = key.to_s.tr(' ', '_').underscore
158
227
  snake.tr!('.', '_')
159
228
 
160
229
  unless excl_list.include?(snake) # Must deal with nested models
161
230
  if value.kind_of?(Array)
162
231
  newval = value.map { |elem| elem.kind_of?(Hash) ? nested_object(snake.camelize.singularize, elem) : elem }
163
- obj[key] = newval
232
+ @hashobj[key] = newval
164
233
  elsif value.kind_of?(Hash)
165
- obj[key] = nested_object(snake.camelize, value)
234
+ @hashobj[key] = nested_object(snake.camelize, value)
166
235
  end
167
236
  end
168
237
 
@@ -212,8 +281,11 @@ module Azure
212
281
 
213
282
  class StorageAccount < BaseModel; end
214
283
  class StorageAccountKey < StorageAccount
215
- def key1; key_name == 'key1' ? value : nil; end
216
- def key2; key_name == 'key2' ? value : nil; end
284
+ attr_from_hash :key_name => :keyName,
285
+ :value => :value
286
+
287
+ def key1; key_name_from_hash == 'key1' ? value_from_hash : nil; end
288
+ def key2; key_name_from_hash == 'key2' ? value_from_hash : nil; end
217
289
  def key; key1 || key2; end
218
290
  end
219
291
 
@@ -5,10 +5,18 @@ require 'nokogiri'
5
5
  module Azure
6
6
  module Armrest
7
7
  class StorageAccount < BaseModel
8
+ attr_from_hash :name => :name,
9
+ :blob_endpoint => [:properties, :primaryEndpoints, :blob]
10
+
8
11
  # Classes used to wrap container and blob information.
9
- class Container < BaseModel; end
12
+ class Container < BaseModel
13
+ attr_from_hash :name => :Name
14
+ end
10
15
  class ContainerProperty < BaseModel; end
11
- class Blob < BaseModel; end
16
+ class Blob < BaseModel
17
+ attr_from_hash :name => :Name,
18
+ :lease_state => [:Properties, :LeaseState]
19
+ end
12
20
  class BlobProperty < BaseModel; end
13
21
  class PrivateImage < BlobProperty; end
14
22
  class BlobServiceProperty < BaseModel; end
@@ -34,7 +42,7 @@ module Azure
34
42
  # The parent configuration object
35
43
  attr_accessor :configuration
36
44
 
37
- def initialize(json)
45
+ def initialize(json, skip_accessors_definition = false)
38
46
  super
39
47
  @storage_api_version = '2016-05-31'
40
48
  end
@@ -424,14 +432,20 @@ module Azure
424
432
  raise ArgumentError, "No access key specified" unless key
425
433
 
426
434
  query = "comp=list"
427
- options.each { |okey, ovalue| query += "&#{okey}=#{[ovalue].flatten.join(',')}" }
435
+ skip_defs = options[:skip_accessors_definition]
436
+
437
+ options.each do |okey, ovalue|
438
+ unless okey == :skip_accessors_definition
439
+ query += "&#{okey}=#{[ovalue].flatten.join(',')}"
440
+ end
441
+ end
428
442
 
429
443
  response = blob_response(key, query)
430
444
 
431
445
  doc = Nokogiri::XML(response.body)
432
446
 
433
447
  results = doc.xpath('//Containers/Container').collect do |element|
434
- Container.new(Hash.from_xml(element.to_s)['Container'])
448
+ Container.new(Hash.from_xml(element.to_s)['Container'], skip_defs)
435
449
  end
436
450
 
437
451
  results.concat(next_marker_results(doc, :containers, key, options))
@@ -468,7 +482,7 @@ module Azure
468
482
  def blob_properties(container, blob, key = access_key, options = {})
469
483
  raise ArgumentError, "No access key specified" unless key
470
484
 
471
- url = File.join(properties.primary_endpoints.blob, container, blob)
485
+ url = File.join(blob_endpoint_from_hash, container, blob)
472
486
  url += "?snapshot=" + options[:date] if options[:date]
473
487
 
474
488
  headers = build_headers(url, key, :blob, :verb => 'HEAD')
@@ -482,7 +496,7 @@ module Azure
482
496
  :ssl_verify => configuration.ssl_verify
483
497
  )
484
498
 
485
- BlobProperty.new(response.headers.merge(:container => container, :name => blob))
499
+ BlobProperty.new(response.headers.merge(:container => container, :name => blob), options[:skip_accessors_definition])
486
500
  end
487
501
 
488
502
  # Update the given +blob+ in +container+ with the provided options. The
@@ -559,7 +573,13 @@ module Azure
559
573
  raise ArgumentError, "No access key specified" unless key
560
574
 
561
575
  query = "restype=container&comp=list"
562
- options.each { |okey, ovalue| query += "&#{okey}=#{[ovalue].flatten.join(',')}" }
576
+ skip_defs = options[:skip_accessors_definition]
577
+
578
+ options.each do |okey, ovalue|
579
+ unless okey == :skip_accessors_definition
580
+ query += "&#{okey}=#{[ovalue].flatten.join(',')}"
581
+ end
582
+ end
563
583
 
564
584
  response = blob_response(key, query, container)
565
585
 
@@ -567,7 +587,7 @@ module Azure
567
587
 
568
588
  results = doc.xpath('//Blobs/Blob').collect do |node|
569
589
  hash = Hash.from_xml(node.to_s)['Blob'].merge(:container => container)
570
- hash.key?('Snapshot') ? BlobSnapshot.new(hash) : Blob.new(hash)
590
+ hash.key?('Snapshot') ? BlobSnapshot.new(hash, skip_defs) : Blob.new(hash, skip_defs)
571
591
  end
572
592
 
573
593
  results.concat(next_marker_results(doc, :blobs, container, key, options))
@@ -582,10 +602,13 @@ module Azure
582
602
 
583
603
  array = []
584
604
  mutex = Mutex.new
605
+ opts = {
606
+ :skip_accessors_definition => options[:skip_accessors_definition]
607
+ }
585
608
 
586
- Parallel.each(containers(key), :in_threads => max_threads) do |container|
609
+ Parallel.each(containers(key, opts), :in_threads => max_threads) do |container|
587
610
  begin
588
- mutex.synchronize { array.concat(blobs(container.name, key, options)) }
611
+ mutex.synchronize { array.concat(blobs(container.name_from_hash, key, options)) }
589
612
  rescue Errno::ECONNREFUSED, Azure::Armrest::TimeoutException => err
590
613
  msg = "Unable to gather blob information for #{container.name}: #{err}"
591
614
  Azure::Armrest::Configuration.log.try(:log, Logger::WARN, msg)
@@ -938,7 +961,7 @@ module Azure
938
961
  # the url and submit an http request.
939
962
  #
940
963
  def blob_response(key, query, *args)
941
- url = File.join(properties.primary_endpoints.blob, *args) + "?#{query}"
964
+ url = File.join(blob_endpoint_from_hash, *args) + "?#{query}"
942
965
  headers = build_headers(url, key, 'blob')
943
966
 
944
967
  ArmrestService.send(
@@ -97,8 +97,9 @@ module Azure
97
97
  url = build_url
98
98
  url = yield(url) || url if block_given?
99
99
 
100
+ skip_accessors_definition = filter.delete(:skip_accessors_definition) || false
100
101
  response = rest_get(url)
101
- results = get_all_results(response)
102
+ results = get_all_results(response, skip_accessors_definition)
102
103
 
103
104
  if filter.empty?
104
105
  results
@@ -106,7 +107,11 @@ module Azure
106
107
  results.select do |obj|
107
108
  filter.all? do |method_name, value|
108
109
  if value.kind_of?(String)
109
- obj.public_send(method_name).casecmp(value).zero?
110
+ if skip_accessors_definition
111
+ obj[method_name.to_s].casecmp(value).zero?
112
+ else
113
+ obj.public_send(method_name).casecmp(value).zero?
114
+ end
110
115
  else
111
116
  obj.public_send(method_name) == value
112
117
  end
@@ -104,7 +104,7 @@ module Azure
104
104
  #
105
105
  # If you want a plain hash, use the list_account_keys method instead.
106
106
  #
107
- def list_account_key_objects(account_name, group = configuration.resource_group)
107
+ def list_account_key_objects(account_name, group = configuration.resource_group, skip_accessors_definition = false)
108
108
  validate_resource_group(group)
109
109
 
110
110
  unless recent_api_version?
@@ -113,7 +113,7 @@ module Azure
113
113
 
114
114
  url = build_url(group, account_name, 'listKeys')
115
115
  response = rest_post(url)
116
- JSON.parse(response.body)['keys'].map { |hash| StorageAccountKey.new(hash) }
116
+ JSON.parse(response.body)['keys'].map { |hash| StorageAccountKey.new(hash, skip_accessors_definition) }
117
117
  end
118
118
 
119
119
  alias list_storage_account_key_objects list_account_key_objects
@@ -172,7 +172,7 @@ module Azure
172
172
  # Note that for string values the comparison is caseless.
173
173
  #
174
174
  def list_all_private_images(filter = {})
175
- storage_accounts = list_all(filter)
175
+ storage_accounts = list_all(filter.merge(:skip_accessors_definition => true))
176
176
  get_private_images(storage_accounts)
177
177
  end
178
178
 
@@ -187,7 +187,7 @@ module Azure
187
187
  # sas.list_private_images(your_resource_group)
188
188
  #
189
189
  def list_private_images(group = configuration.resource_group)
190
- storage_accounts = list(group)
190
+ storage_accounts = list(group, true)
191
191
  get_private_images(storage_accounts)
192
192
  end
193
193
 
@@ -273,30 +273,36 @@ module Azure
273
273
 
274
274
  Parallel.each(storage_accounts, :in_threads => configuration.max_threads) do |storage_account|
275
275
  begin
276
- key = get_account_key(storage_account)
276
+ key = get_account_key(storage_account, true)
277
277
  rescue Azure::Armrest::ApiException
278
278
  next # Most likely due to incomplete or failed provisioning.
279
279
  else
280
280
  storage_account.access_key = key
281
281
  end
282
282
 
283
- storage_account.containers.each do |container|
284
- next if container.name =~ /^bootdiagnostics/i
285
- storage_account.blobs(container.name).each do |blob|
286
- next unless File.extname(blob.name).casecmp('.vhd').zero?
287
- next unless blob.properties.lease_state.casecmp('available').zero?
283
+ init_opts = { :skip_accessors_definition => true }
284
+ storage_account.containers(storage_account.access_key, init_opts).each do |container|
285
+ next if container.name_from_hash =~ /^bootdiagnostics/i
286
+ storage_account.blobs(container.name_from_hash, storage_account.access_key, init_opts).each do |blob|
287
+ next unless File.extname(blob.name_from_hash).casecmp('.vhd').zero?
288
+ next unless blob.lease_state_from_hash.casecmp('available').zero?
288
289
 
289
290
  # In rare cases the endpoint will be unreachable. Warn and move on.
290
291
  begin
291
- blob_properties = storage_account.blob_properties(blob.container, blob.name)
292
+ blob_properties = storage_account.blob_properties(
293
+ blob[:container],
294
+ blob.name_from_hash,
295
+ storage_account.access_key,
296
+ :skip_accessors_definition => true
297
+ )
292
298
  rescue Errno::ECONNREFUSED, Azure::Armrest::TimeoutException => err
293
299
  msg = "Unable to collect blob properties for #{blob.name}/#{blob.container}: #{err}"
294
300
  log('warn', msg)
295
301
  next
296
302
  end
297
303
 
298
- next unless blob_properties.respond_to?(:x_ms_meta_microsoftazurecompute_osstate)
299
- next unless blob_properties.x_ms_meta_microsoftazurecompute_osstate.casecmp('generalized').zero?
304
+ next unless blob_properties[:x_ms_meta_microsoftazurecompute_osstate]
305
+ next unless blob_properties[:x_ms_meta_microsoftazurecompute_osstate].casecmp('generalized').zero?
300
306
 
301
307
  mutex.synchronize do
302
308
  results << blob_to_private_image_object(storage_account, blob, blob_properties)
@@ -315,11 +321,11 @@ module Azure
315
321
  hash = blob.to_h.merge(
316
322
  :storage_account => storage_account.to_h,
317
323
  :blob_properties => blob_properties.to_h,
318
- :operating_system => blob_properties.try(:x_ms_meta_microsoftazurecompute_ostype),
324
+ :operating_system => blob_properties[:x_ms_meta_microsoftazurecompute_ostype],
319
325
  :uri => File.join(
320
- storage_account.properties.primary_endpoints.blob,
321
- blob.container,
322
- blob.name
326
+ storage_account.blob_endpoint_from_hash,
327
+ blob[:container],
328
+ blob.name_from_hash
323
329
  )
324
330
  )
325
331
 
@@ -329,11 +335,11 @@ module Azure
329
335
  # Get the key for the given +storage_acct+ using the appropriate method
330
336
  # depending on the api-version.
331
337
  #
332
- def get_account_key(storage_acct)
338
+ def get_account_key(storage_acct, skip_accessors_definition = false)
333
339
  if recent_api_version?
334
- list_account_key_objects(storage_acct.name, storage_acct.resource_group).first.key
340
+ list_account_key_objects(storage_acct.name_from_hash, storage_acct.resource_group, skip_accessors_definition).first.key
335
341
  else
336
- list_account_keys(storage_acct.name, storage_acct.resource_group).fetch('key1')
342
+ list_account_keys(storage_acct.name_from_hash, storage_acct.resource_group).fetch('key1')
337
343
  end
338
344
  end
339
345
 
@@ -1,6 +1,6 @@
1
1
  module Azure
2
2
  module Armrest
3
3
  # The version of the azure-armrest library.
4
- VERSION = '0.8.4'.freeze
4
+ VERSION = '0.8.5'.freeze
5
5
  end
6
6
  end
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.8.4
4
+ version: 0.8.5
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-10-02 00:00:00.000000000 Z
14
+ date: 2017-10-10 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: json
@@ -302,7 +302,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
302
302
  version: '0'
303
303
  requirements: []
304
304
  rubyforge_project:
305
- rubygems_version: 2.6.11
305
+ rubygems_version: 2.6.14
306
306
  signing_key:
307
307
  specification_version: 4
308
308
  summary: An interface for ARM/JSON Azure REST API