azure-armrest 0.3.5 → 0.3.6
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 +4 -4
- data/.gitignore +1 -0
- data/CHANGES +11 -0
- data/lib/azure/armrest/armrest_collection.rb +28 -0
- data/lib/azure/armrest/armrest_service.rb +38 -0
- data/lib/azure/armrest/exception.rb +25 -3
- data/lib/azure/armrest/insights/event_service.rb +3 -9
- data/lib/azure/armrest/model/base_model.rb +2 -0
- data/lib/azure/armrest/model/storage_account.rb +6 -5
- data/lib/azure/armrest/resource_group_based_service.rb +52 -9
- data/lib/azure/armrest/resource_group_service.rb +1 -2
- data/lib/azure/armrest/resource_service.rb +2 -2
- data/lib/azure/armrest/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d581e8606ff8fb662506a034bd0ba4dca0d5ce02
|
4
|
+
data.tar.gz: f5b4a1c3e4b474db88bab04a40a5b73e395ee2e2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b2a57e5c9b36b7c1bf9d28525cd4d3b3be4772c89b1b9d1342d6773b434846634b458fa8efefbc6f3549f6b6aac469dea7489c9ca44f0b80d45d4f5263cd5863
|
7
|
+
data.tar.gz: 411f85036c00fea64f13ff0c494e2d27172f6fcf67ad029e98b4a3f705f61966179485034c982de7598a6f642c24edd2e4429fbd13f0457ec80ac4d70f556f70
|
data/.gitignore
CHANGED
data/CHANGES
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
= 0.3.6 - 13-Sep-2016
|
2
|
+
* Added the poll and wait methods to the ArmrestService base class. These
|
3
|
+
are meant for use with asynchronous operations, e.g. create and delete.
|
4
|
+
* All methods that returned a plain array now return an ArmrestCollection
|
5
|
+
object instead. This is a subclass of Array, but includes header and
|
6
|
+
skip token information.
|
7
|
+
* Added the ArmrestCollection.create_from_response method. This creates
|
8
|
+
and returns a collection based on a JSON response and a model type.
|
9
|
+
* Minor update to the ApiException#to_s method so that includes a bit
|
10
|
+
more information.
|
11
|
+
|
1
12
|
= 0.3.5 - 11-Aug-2016
|
2
13
|
* When we added subscription ID validation in 0.3.2 we forgot to set proxy
|
3
14
|
information first. That has been fixed.
|
@@ -4,6 +4,34 @@ module Azure
|
|
4
4
|
module Armrest
|
5
5
|
class ArmrestCollection < Array
|
6
6
|
attr_accessor :continuation_token
|
7
|
+
attr_accessor :response_headers
|
8
|
+
|
9
|
+
alias skip_token continuation_token
|
10
|
+
alias skip_token= continuation_token=
|
11
|
+
|
12
|
+
class << self
|
13
|
+
# Creates and returns a ArmrestCollection object based on JSON input,
|
14
|
+
# using +klass+ to generate the list elements. In addition, both the
|
15
|
+
# response headers and continuation token are set.
|
16
|
+
#
|
17
|
+
def create_from_response(response, klass = nil)
|
18
|
+
json_response = JSON.parse(response)
|
19
|
+
array = new(json_response['value'].map { |hash| klass.new(hash) })
|
20
|
+
|
21
|
+
array.response_headers = response.headers
|
22
|
+
array.continuation_token = parse_skip_token(json_response)
|
23
|
+
|
24
|
+
array
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
# Parse the skip token value out of the nextLink attribute from a response.
|
30
|
+
def parse_skip_token(json)
|
31
|
+
return nil unless json['nextLink']
|
32
|
+
json['nextLink'][/.*?skipToken=(.*?)$/i, 1]
|
33
|
+
end
|
34
|
+
end
|
7
35
|
end
|
8
36
|
end
|
9
37
|
end
|
@@ -157,6 +157,44 @@ module Azure
|
|
157
157
|
JSON.parse(resp.body)['value'].map{ |hash| Azure::Armrest::Tenant.new(hash) }
|
158
158
|
end
|
159
159
|
|
160
|
+
# Poll a resource and return its current operations status. The
|
161
|
+
# +response+ argument should be a ResponseHeaders object that
|
162
|
+
# contains the :azure_asyncoperation header. It may optionally
|
163
|
+
# be an object that returns a URL from a .to_s method.
|
164
|
+
#
|
165
|
+
# This is meant to check the status of asynchronous operations,
|
166
|
+
# such as create or delete.
|
167
|
+
#
|
168
|
+
def poll(response)
|
169
|
+
url = response.respond_to?(:azure_asyncoperation) ? response.azure_asyncoperation : response.to_s
|
170
|
+
JSON.parse(rest_get(url))['status']
|
171
|
+
end
|
172
|
+
|
173
|
+
# Wait for the given +response+ to return a status of 'Succeeded', up
|
174
|
+
# to a maximum of +max_time+ seconds, and return the operations status.
|
175
|
+
# The first argument must be a ResponseHeaders object that contains
|
176
|
+
# the azure_asyncoperation header.
|
177
|
+
#
|
178
|
+
# Internally this will poll the response header every :retry_after
|
179
|
+
# seconds (or 10 seconds if that header isn't found), up to a maximum of
|
180
|
+
# 60 seconds by default.
|
181
|
+
#
|
182
|
+
# For most resources the +max_time+ argument should be more than sufficient.
|
183
|
+
# Certain resources, such as virtual machines, could take longer.
|
184
|
+
#
|
185
|
+
def wait(response, max_time = 60)
|
186
|
+
sleep_time = response.respond_to?(:retry_after) ? response.retry_after.to_i : 10
|
187
|
+
total_time = 0
|
188
|
+
|
189
|
+
while (status = poll(response)).casecmp('Succeeded') != 0
|
190
|
+
total_time += sleep_time
|
191
|
+
break if total_time >= max_time
|
192
|
+
sleep sleep_time
|
193
|
+
end
|
194
|
+
|
195
|
+
status
|
196
|
+
end
|
197
|
+
|
160
198
|
class << self
|
161
199
|
private
|
162
200
|
|
@@ -4,15 +4,30 @@ module Azure
|
|
4
4
|
attr_accessor :cause
|
5
5
|
attr_writer :message
|
6
6
|
|
7
|
+
# Create a new Armrest::Exception object. The +message+ should be an
|
8
|
+
# error string, while +cause_exception+ is typically set to the
|
9
|
+
# raw RestClient exception.
|
10
|
+
#
|
11
|
+
# You will not typically use this object directly.
|
12
|
+
#
|
7
13
|
def initialize(message = nil, cause_exception = nil)
|
8
14
|
@message = message
|
9
15
|
@cause = cause_exception
|
10
16
|
end
|
11
17
|
|
18
|
+
# The stringified version (message) of the exception.
|
19
|
+
#
|
12
20
|
def to_s
|
13
|
-
|
21
|
+
if cause
|
22
|
+
"#{message} (cause: #{cause})"
|
23
|
+
else
|
24
|
+
message
|
25
|
+
end
|
14
26
|
end
|
15
27
|
|
28
|
+
# The error message or, if the message is not set, the name of the
|
29
|
+
# exception class.
|
30
|
+
#
|
16
31
|
def message
|
17
32
|
@message || self.class.name
|
18
33
|
end
|
@@ -21,16 +36,24 @@ module Azure
|
|
21
36
|
class ApiException < Exception
|
22
37
|
attr_accessor :code
|
23
38
|
|
39
|
+
# Create a new ApiException class. The +code+ is the error code.
|
40
|
+
#
|
41
|
+
# This class serves as the parent
|
24
42
|
def initialize(code, message, cause_exception)
|
25
43
|
@code = code
|
26
44
|
super(message, cause_exception)
|
27
45
|
end
|
28
46
|
|
47
|
+
# A stringified version of the error. If self is a plain ApiException,
|
48
|
+
# then the cause is included to aid in debugging.
|
49
|
+
#
|
29
50
|
def to_s
|
30
|
-
"[#{code}] #{
|
51
|
+
"[#{code}] #{super}"
|
31
52
|
end
|
32
53
|
end
|
33
54
|
|
55
|
+
# A list of predefined exceptions that we wrap around RestClient exceptions.
|
56
|
+
|
34
57
|
class ResourceNotFoundException < ApiException; end
|
35
58
|
|
36
59
|
class BadRequestException < ApiException; end
|
@@ -42,6 +65,5 @@ module Azure
|
|
42
65
|
class GatewayTimeoutException < ApiException; end
|
43
66
|
|
44
67
|
class TooManyRequestsException < ApiException; end
|
45
|
-
|
46
68
|
end
|
47
69
|
end
|
@@ -44,22 +44,16 @@ module Azure
|
|
44
44
|
# filter = "eventTimestamp ge #{date} and eventChannels eq 'Admin, Operation'"
|
45
45
|
# select = "resourceGroupName, operationName"
|
46
46
|
#
|
47
|
-
# ies.list(:filter => filter, :select => select, :all => true).
|
47
|
+
# ies.list(:filter => filter, :select => select, :all => true).each{ |event|
|
48
48
|
# p event
|
49
49
|
# }
|
50
50
|
#
|
51
51
|
def list(options = {})
|
52
52
|
url = build_url(options)
|
53
53
|
response = rest_get(url)
|
54
|
-
json_response = JSON.parse(response.body)
|
55
54
|
|
56
|
-
|
57
|
-
|
58
|
-
Azure::Armrest::Insights::Event.new(hash)
|
59
|
-
end
|
60
|
-
)
|
61
|
-
|
62
|
-
events.continuation_token = parse_skip_token(json_response)
|
55
|
+
klass = Azure::Armrest::Insights::Event
|
56
|
+
events = Azure::Armrest::ArmrestCollection.create_from_response(response, klass)
|
63
57
|
|
64
58
|
if options[:all] && events.continuation_token
|
65
59
|
events.push(*list(options.merge(:skip_token => events.continuation_token)))
|
@@ -22,6 +22,8 @@ module Azure
|
|
22
22
|
|
23
23
|
attr_hash :tags
|
24
24
|
|
25
|
+
attr_accessor :response_headers
|
26
|
+
|
25
27
|
# Constructs and returns a new JSON wrapper class. Pass in a plain
|
26
28
|
# JSON string and it will automatically give you accessor methods
|
27
29
|
# that make it behave like a typical Ruby object. You may also pass
|
@@ -21,7 +21,7 @@ module Azure
|
|
21
21
|
class TableData < BaseModel; end
|
22
22
|
|
23
23
|
# The version string used in headers sent as part any internal http
|
24
|
-
# request. The default is 2015-
|
24
|
+
# request. The default is 2015-12-11.
|
25
25
|
attr_accessor :storage_api_version
|
26
26
|
|
27
27
|
# An http proxy to use per request. Defaults to ENV['http_proxy'] if set.
|
@@ -35,7 +35,7 @@ module Azure
|
|
35
35
|
|
36
36
|
def initialize(json)
|
37
37
|
super
|
38
|
-
@storage_api_version = '2015-
|
38
|
+
@storage_api_version = '2015-12-11'
|
39
39
|
@proxy = ENV['http_proxy']
|
40
40
|
@ssl_version = 'TLSv1'
|
41
41
|
@ssl_verify = nil
|
@@ -99,11 +99,12 @@ module Azure
|
|
99
99
|
key ||= properties.key1
|
100
100
|
|
101
101
|
query = build_query(options)
|
102
|
-
|
103
102
|
response = table_response(key, query, name)
|
104
|
-
json_response = JSON.parse(response.body)
|
105
103
|
|
106
|
-
|
104
|
+
klass = Azure::Armrest::StorageAccount::TableData
|
105
|
+
data = Azure::Armrest::ArmrestCollection.create_from_response(response, klass)
|
106
|
+
|
107
|
+
# Continuation tokens are parsed differently for storage
|
107
108
|
data.continuation_token = parse_continuation_tokens(response)
|
108
109
|
|
109
110
|
if options[:all] && data.continuation_token
|
@@ -2,6 +2,17 @@ module Azure
|
|
2
2
|
module Armrest
|
3
3
|
# Base class for services that need to run in a resource group
|
4
4
|
class ResourceGroupBasedService < ArmrestService
|
5
|
+
# Create a resource +name+ within the resource group +rgroup+, or the
|
6
|
+
# resource group that was specified in the configuration, along with
|
7
|
+
# a hash of appropriate +options+.
|
8
|
+
#
|
9
|
+
# Returns an instance of the object that was created if possible,
|
10
|
+
# otherwise nil is returned.
|
11
|
+
#
|
12
|
+
# Note that this is an asynchronous operation. You can check the current
|
13
|
+
# status of the resource by inspecting the :response_headers instance and
|
14
|
+
# polling either the :azure_asyncoperation or :location URL.
|
15
|
+
#
|
5
16
|
def create(name, rgroup = configuration.resource_group, options = {})
|
6
17
|
validate_resource_group(rgroup)
|
7
18
|
validate_resource(name)
|
@@ -9,18 +20,33 @@ module Azure
|
|
9
20
|
url = build_url(rgroup, name)
|
10
21
|
url = yield(url) || url if block_given?
|
11
22
|
response = rest_put(url, options.to_json)
|
12
|
-
|
23
|
+
|
24
|
+
obj = nil
|
25
|
+
|
26
|
+
unless response.empty?
|
27
|
+
obj = model_class.new(response.body)
|
28
|
+
obj.response_headers = Azure::Armrest::ResponseHeaders.new(response.headers)
|
29
|
+
end
|
30
|
+
|
31
|
+
obj
|
13
32
|
end
|
14
33
|
|
15
34
|
alias update create
|
16
35
|
|
36
|
+
# List all resources within the resource group +rgroup+, or the
|
37
|
+
# resource group that was specified in the configuration.
|
38
|
+
#
|
39
|
+
# Returns an ArmrestCollection, with the response headers set
|
40
|
+
# for the operation as a whole.
|
41
|
+
#
|
17
42
|
def list(rgroup = configuration.resource_group)
|
18
43
|
validate_resource_group(rgroup)
|
19
44
|
|
20
45
|
url = build_url(rgroup)
|
21
46
|
url = yield(url) || url if block_given?
|
22
47
|
response = rest_get(url)
|
23
|
-
|
48
|
+
|
49
|
+
Azure::Armrest::ArmrestCollection.create_from_response(response, model_class)
|
24
50
|
end
|
25
51
|
|
26
52
|
# Use a single call to get all resources for the service. You may
|
@@ -35,11 +61,16 @@ module Azure
|
|
35
61
|
def list_all(filter = {})
|
36
62
|
url = build_url
|
37
63
|
url = yield(url) || url if block_given?
|
64
|
+
|
38
65
|
response = rest_get(url)
|
39
|
-
results
|
66
|
+
results = Azure::Armrest::ArmrestCollection.create_from_response(response, model_class)
|
67
|
+
|
40
68
|
filter.empty? ? results : results.select { |obj| filter.all? { |k, v| obj.public_send(k) == v } }
|
41
69
|
end
|
42
70
|
|
71
|
+
# Get information about a single resource +name+ within resource group
|
72
|
+
# +rgroup+, or the resource group that was set in the configuration.
|
73
|
+
#
|
43
74
|
def get(name, rgroup = configuration.resource_group)
|
44
75
|
validate_resource_group(rgroup)
|
45
76
|
validate_resource(name)
|
@@ -47,7 +78,11 @@ module Azure
|
|
47
78
|
url = build_url(rgroup, name)
|
48
79
|
url = yield(url) || url if block_given?
|
49
80
|
response = rest_get(url)
|
50
|
-
|
81
|
+
|
82
|
+
obj = model_class.new(response.body)
|
83
|
+
obj.response_headers = Azure::Armrest::ResponseHeaders.new(response.headers)
|
84
|
+
|
85
|
+
obj
|
51
86
|
end
|
52
87
|
|
53
88
|
# Delete the resource with the given +name+ for the provided +resource_group+,
|
@@ -101,19 +136,27 @@ module Azure
|
|
101
136
|
|
102
137
|
# Aggregate resources from all resource groups.
|
103
138
|
#
|
104
|
-
# To be used in the cases where the API does not support list_all with
|
139
|
+
# To be used in the cases where the API does not support list_all with
|
140
|
+
# one call. Note that this does not set the skip token because we're
|
141
|
+
# actually collating the results of multiple calls internally.
|
105
142
|
#
|
106
143
|
def list_in_all_groups
|
107
|
-
array
|
108
|
-
mutex
|
144
|
+
array = []
|
145
|
+
mutex = Mutex.new
|
146
|
+
headers = nil
|
109
147
|
|
110
148
|
Parallel.each(list_resource_groups, :in_threads => configuration.max_threads) do |rg|
|
111
149
|
response = rest_get(build_url(rg.name))
|
112
|
-
|
150
|
+
json_response = JSON.parse(response.body)['value']
|
151
|
+
headers = Azure::Armrest::ResponseHeaders.new(response.headers)
|
152
|
+
results = json_response.map { |hash| model_class.new(hash) }
|
113
153
|
mutex.synchronize { array << results } unless results.blank?
|
114
154
|
end
|
115
155
|
|
116
|
-
array.flatten
|
156
|
+
array = ArmrestCollection.new(array.flatten)
|
157
|
+
array.response_headers = headers # Use the last set of headers for the overall result
|
158
|
+
|
159
|
+
array
|
117
160
|
end
|
118
161
|
end
|
119
162
|
end
|
@@ -26,8 +26,7 @@ module Azure
|
|
26
26
|
url << "&$filter=#{options[:filter]}" if options[:filter]
|
27
27
|
|
28
28
|
response = rest_get(url)
|
29
|
-
|
30
|
-
JSON.parse(response)['value'].map { |hash| Azure::Armrest::ResourceGroup.new(hash) }
|
29
|
+
Azure::Armrest::ArmrestCollection.create_from_response(response, Azure::Armrest::ResourceGroup)
|
31
30
|
end
|
32
31
|
|
33
32
|
# Creates a new +group+ in +location+ for the current subscription.
|
@@ -23,7 +23,7 @@ module Azure
|
|
23
23
|
def list(resource_group, options = {})
|
24
24
|
url = build_url(resource_group, options)
|
25
25
|
response = rest_get(url)
|
26
|
-
|
26
|
+
Azure::Armrest::ArmrestCollection.create_from_response(response, Azure::Armrest::Resource)
|
27
27
|
end
|
28
28
|
|
29
29
|
# Same as Azure::Armrest::ResourceService#list but returns all resources
|
@@ -32,7 +32,7 @@ module Azure
|
|
32
32
|
def list_all(options = {})
|
33
33
|
url = build_url(nil, options)
|
34
34
|
response = rest_get(url)
|
35
|
-
|
35
|
+
Azure::Armrest::ArmrestCollection.create_from_response(response, Azure::Armrest::Resource)
|
36
36
|
end
|
37
37
|
|
38
38
|
# Move the resources from +source_group+ under +source_subscription+,
|
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.3.
|
4
|
+
version: 0.3.6
|
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: 2016-
|
14
|
+
date: 2016-09-13 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: json
|