azure-armrest 0.3.5 → 0.3.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|