vmware-vra 1.5.4 → 1.6.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 +4 -4
- data/CHANGELOG.md +4 -1
- data/lib/vra/catalog_item.rb +1 -1
- data/lib/vra/catalog_request.rb +1 -1
- data/lib/vra/client.rb +26 -29
- data/lib/vra/http.rb +142 -0
- data/lib/vra/request.rb +1 -1
- data/lib/vra/resource.rb +2 -2
- data/lib/vra/version.rb +1 -1
- data/spec/catalog_request_spec.rb +1 -1
- data/spec/client_spec.rb +65 -85
- data/spec/http_spec.rb +146 -0
- data/spec/request_spec.rb +2 -2
- data/spec/resource_spec.rb +4 -4
- data/vmware-vra.gemspec +0 -1
- metadata +6 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 32967b6a528fdaea4b4c969fcc58ea9f1e84bd1a
|
4
|
+
data.tar.gz: 023a8634851534b756d4651373665802fb96c75b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4b54eb12f4e39519bb79fba806443064e019a34a917d9b1710186fa55ce99ecd9571e681b638df8bfadcc5d26398f7235e5476522d4984c293b456b39fdde91a
|
7
|
+
data.tar.gz: e59668d3a5130eb86d671d57bd5ecc83b1b31fb3c7d4b052faf75ce8fd1da241e51440bc2ccf38bd52519c8d70ab70e235d231849457c055b8b58ea795417af6
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
# vmware-vra-gem CHANGELOG
|
2
2
|
|
3
|
+
## v1.6.0 (2016-05-10)
|
4
|
+
* [pr#28](https://github.com/chef-partners/vmware-vra-gem/pull/28) Remove rest-client dependency
|
5
|
+
|
3
6
|
## v1.5.4 (2016-04-27)
|
4
7
|
* [pr#29](https://github.com/chef-partners/vmware-vra-gem/pull/29) Bug fix: handle more gracefully the situations where a resource or catalog item is missing data in the API response
|
5
8
|
|
@@ -25,7 +28,7 @@
|
|
25
28
|
* [pr#11](https://github.com/chef-partners/vmware-vra-gem/pull/11) Ability to set paginated results page size, which is a workaround for issue reported in #10 regarding duplicate items returned in paginated results.
|
26
29
|
|
27
30
|
## v1.1.0
|
28
|
-
* [pr#9](https://github.com/chef-partners/vmware-vra-gem/pull/9) Mask password and bearer token in console/debug/log output.
|
31
|
+
* [pr#9](https://github.com/chef-partners/vmware-vra-gem/pull/9) Mask password and bearer token in console/debug/log output.
|
29
32
|
Thanks to [@rubytester](https://github.com/rubytester) for the idea and initial proposal to address in [pr#7](https://github.com/chef-partners/vmware-vra-gem/pull/7)
|
30
33
|
|
31
34
|
## v1.0.0
|
data/lib/vra/catalog_item.rb
CHANGED
@@ -42,7 +42,7 @@ module Vra
|
|
42
42
|
end
|
43
43
|
|
44
44
|
def fetch_catalog_item
|
45
|
-
@catalog_item_data =
|
45
|
+
@catalog_item_data = client.get_parsed("/catalog-service/api/consumer/catalogItems/#{id}")
|
46
46
|
rescue Vra::Exception::HTTPNotFound
|
47
47
|
raise Vra::Exception::NotFound, "catalog ID #{id} does not exist"
|
48
48
|
end
|
data/lib/vra/catalog_request.rb
CHANGED
data/lib/vra/client.rb
CHANGED
@@ -17,8 +17,8 @@
|
|
17
17
|
#
|
18
18
|
|
19
19
|
require 'ffi_yajl'
|
20
|
-
require 'rest-client'
|
21
20
|
require 'passwordmasker'
|
21
|
+
require 'vra/http'
|
22
22
|
|
23
23
|
module Vra
|
24
24
|
# rubocop:disable ClassLength
|
@@ -93,19 +93,17 @@ module Vra
|
|
93
93
|
return false if @bearer_token.value.nil?
|
94
94
|
|
95
95
|
response = http_head("/identity/api/tokens/#{@bearer_token.value}", :skip_auth)
|
96
|
-
|
97
|
-
true
|
98
|
-
else
|
99
|
-
false
|
100
|
-
end
|
96
|
+
response.success_no_content?
|
101
97
|
end
|
102
98
|
|
103
99
|
def generate_bearer_token
|
104
100
|
@bearer_token.value = nil
|
105
101
|
validate_client_options!
|
106
102
|
|
107
|
-
response = http_post('/identity/api/tokens',
|
108
|
-
|
103
|
+
response = http_post('/identity/api/tokens',
|
104
|
+
FFI_Yajl::Encoder.encode(bearer_token_request_body),
|
105
|
+
:skip_auth)
|
106
|
+
unless response.success_ok?
|
109
107
|
raise Vra::Exception::Unauthorized, "Unable to get bearer token: #{response.body}"
|
110
108
|
end
|
111
109
|
|
@@ -116,30 +114,25 @@ module Vra
|
|
116
114
|
"#{@base_url}#{path}"
|
117
115
|
end
|
118
116
|
|
119
|
-
def
|
117
|
+
def http_fetch(method, path, skip_auth=nil)
|
120
118
|
authorize! unless skip_auth
|
121
119
|
|
122
|
-
response =
|
123
|
-
|
124
|
-
|
125
|
-
|
120
|
+
response = Vra::Http.execute(method: method,
|
121
|
+
url: full_url(path),
|
122
|
+
headers: request_headers,
|
123
|
+
verify_ssl: @verify_ssl)
|
126
124
|
rescue => e
|
127
125
|
raise_http_exception(e, path)
|
128
126
|
else
|
129
127
|
response
|
130
128
|
end
|
131
129
|
|
132
|
-
def
|
133
|
-
|
130
|
+
def http_head(path, skip_auth=nil)
|
131
|
+
http_fetch(:head, path, skip_auth)
|
132
|
+
end
|
134
133
|
|
135
|
-
|
136
|
-
|
137
|
-
headers: request_headers,
|
138
|
-
verify_ssl: @verify_ssl)
|
139
|
-
rescue => e
|
140
|
-
raise_http_exception(e, path)
|
141
|
-
else
|
142
|
-
response
|
134
|
+
def http_get(path, skip_auth=nil)
|
135
|
+
http_fetch(:get, path, skip_auth)
|
143
136
|
end
|
144
137
|
|
145
138
|
def http_get!(path)
|
@@ -147,13 +140,17 @@ module Vra
|
|
147
140
|
response.body
|
148
141
|
end
|
149
142
|
|
143
|
+
def get_parsed(path)
|
144
|
+
FFI_Yajl::Parser.parse(http_get!(path))
|
145
|
+
end
|
146
|
+
|
150
147
|
def http_get_paginated_array!(path)
|
151
148
|
items = []
|
152
149
|
page = 1
|
153
150
|
base_path = path + "?limit=#{page_size}"
|
154
151
|
|
155
152
|
loop do
|
156
|
-
response =
|
153
|
+
response = get_parsed("#{base_path}&page=#{page}")
|
157
154
|
items += response['content']
|
158
155
|
|
159
156
|
break if page >= response['metadata']['totalPages']
|
@@ -172,11 +169,11 @@ module Vra
|
|
172
169
|
def http_post(path, payload, skip_auth=nil)
|
173
170
|
authorize! unless skip_auth
|
174
171
|
|
175
|
-
response =
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
172
|
+
response = Vra::Http.execute(method: :post,
|
173
|
+
url: full_url(path),
|
174
|
+
headers: request_headers,
|
175
|
+
payload: payload,
|
176
|
+
verify_ssl: @verify_ssl)
|
180
177
|
rescue => e
|
181
178
|
raise_http_exception(e, path)
|
182
179
|
else
|
data/lib/vra/http.rb
ADDED
@@ -0,0 +1,142 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
|
3
|
+
module Vra
|
4
|
+
module Http
|
5
|
+
def self.execute(params)
|
6
|
+
request = Request.new(params)
|
7
|
+
response = request.call
|
8
|
+
response = response.forward(request).call until response.final?
|
9
|
+
fail error(response) unless response.success?
|
10
|
+
response
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.error(response)
|
14
|
+
Error.from_response(response)
|
15
|
+
end
|
16
|
+
|
17
|
+
class Request
|
18
|
+
attr_reader :params
|
19
|
+
|
20
|
+
def initialize(params)
|
21
|
+
@params = params
|
22
|
+
end
|
23
|
+
|
24
|
+
def redirectable?
|
25
|
+
[:get, :head].include?(params[:method])
|
26
|
+
end
|
27
|
+
|
28
|
+
def redirect_to(location)
|
29
|
+
new(url: location)
|
30
|
+
end
|
31
|
+
|
32
|
+
def see_other(location)
|
33
|
+
redirect_to(location).new(method: :get)
|
34
|
+
end
|
35
|
+
|
36
|
+
def call
|
37
|
+
uri = URI(params[:url]) || fail(':url required')
|
38
|
+
|
39
|
+
Net::HTTP.start(uri.host, uri.port,
|
40
|
+
use_ssl: uri.scheme == 'https') do |http|
|
41
|
+
request = http_request(params[:method], uri)
|
42
|
+
request.initialize_http_header(params[:headers] || {})
|
43
|
+
request.body = params[:payload] || ''
|
44
|
+
|
45
|
+
Response.new(http.request(request))
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def http_request(method, uri)
|
50
|
+
type = {
|
51
|
+
get: Net::HTTP::Get,
|
52
|
+
head: Net::HTTP::Head,
|
53
|
+
post: Net::HTTP::Post
|
54
|
+
}.fetch(method, nil)
|
55
|
+
|
56
|
+
fail "Unknown HTTP method #{method}!" unless type
|
57
|
+
|
58
|
+
type.new(uri)
|
59
|
+
end
|
60
|
+
|
61
|
+
protected
|
62
|
+
|
63
|
+
def new(new_params)
|
64
|
+
self.class.new(params.dup.merge(new_params))
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
class Response
|
69
|
+
# For hiding the details of the HTTP response class
|
70
|
+
# so it can be swapped out easily
|
71
|
+
def initialize(response)
|
72
|
+
@response = response
|
73
|
+
end
|
74
|
+
|
75
|
+
def forward(request)
|
76
|
+
if redirect?
|
77
|
+
fail Http.error(self) unless request.redirectable?
|
78
|
+
request.redirect_to(location)
|
79
|
+
elsif see_other?
|
80
|
+
request.see_other(location)
|
81
|
+
else
|
82
|
+
request
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def location
|
87
|
+
@response['location']
|
88
|
+
end
|
89
|
+
|
90
|
+
def body
|
91
|
+
@response.body
|
92
|
+
end
|
93
|
+
|
94
|
+
def code
|
95
|
+
@response.code.to_i
|
96
|
+
end
|
97
|
+
|
98
|
+
def message
|
99
|
+
@response.message
|
100
|
+
end
|
101
|
+
|
102
|
+
def success_ok?
|
103
|
+
code == 200
|
104
|
+
end
|
105
|
+
|
106
|
+
def success_no_content?
|
107
|
+
code == 204
|
108
|
+
end
|
109
|
+
|
110
|
+
def success?
|
111
|
+
(200..207).cover?(code)
|
112
|
+
end
|
113
|
+
|
114
|
+
def redirect?
|
115
|
+
[301, 302, 307].include?(code)
|
116
|
+
end
|
117
|
+
|
118
|
+
def see_other?
|
119
|
+
code == 303
|
120
|
+
end
|
121
|
+
|
122
|
+
def final?
|
123
|
+
!(redirect? || see_other?)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
class Error < StandardError
|
128
|
+
def self.from_response(http_response)
|
129
|
+
new(http_response.message, http_response.code, http_response.body)
|
130
|
+
end
|
131
|
+
|
132
|
+
attr_reader :http_code
|
133
|
+
attr_reader :response
|
134
|
+
|
135
|
+
def initialize(message, http_code, response)
|
136
|
+
super(message)
|
137
|
+
@http_code = http_code
|
138
|
+
@response = response
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
data/lib/vra/request.rb
CHANGED
@@ -32,7 +32,7 @@ module Vra
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def refresh
|
35
|
-
@request_data =
|
35
|
+
@request_data = client.get_parsed("/catalog-service/api/consumer/requests/#{@id}")
|
36
36
|
rescue Vra::Exception::HTTPNotFound
|
37
37
|
raise Vra::Exception::NotFound, "request ID #{@id} is not found"
|
38
38
|
end
|
data/lib/vra/resource.rb
CHANGED
@@ -45,7 +45,7 @@ module Vra
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def fetch_resource_data
|
48
|
-
@resource_data =
|
48
|
+
@resource_data = client.get_parsed("/catalog-service/api/consumer/resources/#{@id}")
|
49
49
|
rescue Vra::Exception::HTTPNotFound
|
50
50
|
raise Vra::Exception::NotFound, "resource ID #{@id} does not exist"
|
51
51
|
end
|
@@ -239,7 +239,7 @@ module Vra
|
|
239
239
|
def submit_action_request(action_id)
|
240
240
|
payload = action_request_payload(action_id).to_json
|
241
241
|
response = client.http_post('/catalog-service/api/consumer/requests', payload)
|
242
|
-
request_id = response.
|
242
|
+
request_id = response.location.split('/')[-1]
|
243
243
|
Vra::Request.new(client, request_id)
|
244
244
|
end
|
245
245
|
end
|
data/lib/vra/version.rb
CHANGED
@@ -106,7 +106,7 @@ describe Vra::CatalogRequest do
|
|
106
106
|
describe '#submit' do
|
107
107
|
before do
|
108
108
|
allow(request).to receive(:request_payload).and_return({})
|
109
|
-
response = double('response',
|
109
|
+
response = double('response', location: '/requests/request-12345')
|
110
110
|
allow(client).to receive(:http_post).with('/catalog-service/api/consumer/requests', '{}').and_return(response)
|
111
111
|
end
|
112
112
|
|
data/spec/client_spec.rb
CHANGED
@@ -104,20 +104,16 @@ describe Vra::Client do
|
|
104
104
|
client.bearer_token = '12345'
|
105
105
|
end
|
106
106
|
|
107
|
-
url = '/identity/api/tokens/12345'
|
108
|
-
|
109
107
|
it 'returns true if the token validates successfully' do
|
110
|
-
response = double('response')
|
111
|
-
allow(
|
112
|
-
allow(client).to receive(:http_head).with(url, :skip_auth).and_return(response)
|
108
|
+
response = double('response', success_no_content?: true, code: 204)
|
109
|
+
allow(Vra::Http).to receive(:execute).and_return(response)
|
113
110
|
|
114
111
|
expect(client.authorized?).to be true
|
115
112
|
end
|
116
113
|
|
117
114
|
it 'returns false if the token validates unsuccessfully' do
|
118
|
-
response = double('response')
|
119
|
-
allow(
|
120
|
-
allow(client).to receive(:http_head).with(url, :skip_auth).and_return(response)
|
115
|
+
response = double('response', success_no_content?: false, code: 500)
|
116
|
+
allow(Vra::Http).to receive(:execute).and_return(response)
|
121
117
|
|
122
118
|
expect(client.authorized?).to be false
|
123
119
|
end
|
@@ -132,24 +128,22 @@ describe Vra::Client do
|
|
132
128
|
}.to_json
|
133
129
|
|
134
130
|
it 'posts to the tokens API endpoint' do
|
135
|
-
response = double('response')
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
131
|
+
response = double('response', code: 200, body: '{"id":"12345"}', success_ok?: true)
|
132
|
+
expect(Vra::Http).to receive(:execute)
|
133
|
+
.with(method: :post,
|
134
|
+
url: client.full_url('/identity/api/tokens'),
|
135
|
+
payload: payload,
|
136
|
+
headers: anything,
|
137
|
+
verify_ssl: true)
|
138
|
+
.and_return(response)
|
141
139
|
|
142
140
|
client.generate_bearer_token
|
143
141
|
end
|
144
142
|
|
145
143
|
context 'when token is generated successfully' do
|
146
144
|
it 'sets the token' do
|
147
|
-
response = double('response')
|
148
|
-
allow(
|
149
|
-
allow(response).to receive(:body).and_return('{"id":"12345"}')
|
150
|
-
allow(client).to receive(:http_post).with('/identity/api/tokens',
|
151
|
-
payload,
|
152
|
-
:skip_auth).and_return(response)
|
145
|
+
response = double('response', code: 200, body: '{"id":"12345"}', success_ok?: true)
|
146
|
+
allow(Vra::Http).to receive(:execute).and_return(response)
|
153
147
|
|
154
148
|
client.generate_bearer_token
|
155
149
|
|
@@ -159,13 +153,8 @@ describe Vra::Client do
|
|
159
153
|
|
160
154
|
context 'when token is not generated successfully' do
|
161
155
|
it 'raises an exception' do
|
162
|
-
response = double('response')
|
163
|
-
allow(
|
164
|
-
allow(response).to receive(:body).and_return('error string')
|
165
|
-
allow(client).to receive(:http_post).with('/identity/api/tokens',
|
166
|
-
payload,
|
167
|
-
:skip_auth)
|
168
|
-
.and_return(response)
|
156
|
+
response = double('response', code: 500, body: 'error string', success_ok?: false)
|
157
|
+
allow(Vra::Http).to receive(:execute).and_return(response)
|
169
158
|
|
170
159
|
expect { client.generate_bearer_token }.to raise_error(Vra::Exception::Unauthorized)
|
171
160
|
end
|
@@ -182,7 +171,7 @@ describe Vra::Client do
|
|
182
171
|
context 'when skip_auth is nil' do
|
183
172
|
it 'authorizes before proceeding' do
|
184
173
|
response = double('response')
|
185
|
-
allow(
|
174
|
+
allow(Vra::Http).to receive(:execute).and_return(response)
|
186
175
|
expect(client).to receive(:authorize!)
|
187
176
|
|
188
177
|
client.http_head('/test')
|
@@ -192,14 +181,14 @@ describe Vra::Client do
|
|
192
181
|
context 'when skip_auth is not nil' do
|
193
182
|
it 'does not authorize before proceeding' do
|
194
183
|
response = double('response')
|
195
|
-
allow(
|
184
|
+
allow(Vra::Http).to receive(:execute).and_return(response)
|
196
185
|
expect(client).to_not receive(:authorize!)
|
197
186
|
|
198
187
|
client.http_head('/test', :skip_auth)
|
199
188
|
end
|
200
189
|
end
|
201
190
|
|
202
|
-
it 'calls
|
191
|
+
it 'calls Vra::Http.execute' do
|
203
192
|
response = double('response')
|
204
193
|
path = '/test'
|
205
194
|
full_url = 'https://vra.corp.local/test'
|
@@ -207,21 +196,21 @@ describe Vra::Client do
|
|
207
196
|
verify_ssl = true
|
208
197
|
|
209
198
|
allow(client).to receive(:authorize!)
|
210
|
-
expect(
|
211
|
-
|
212
|
-
|
213
|
-
|
199
|
+
expect(Vra::Http).to receive(:execute).with(method: :head,
|
200
|
+
url: full_url,
|
201
|
+
headers: headers,
|
202
|
+
verify_ssl: verify_ssl)
|
214
203
|
.and_return(response)
|
215
204
|
|
216
205
|
client.http_head(path)
|
217
206
|
end
|
218
207
|
|
219
|
-
it '
|
208
|
+
it 'raises an HTTPNotFound on a 404 error' do
|
220
209
|
allow(client).to receive(:authorize!)
|
221
|
-
allow(
|
222
|
-
|
210
|
+
allow(Vra::Http).to receive(:execute)
|
211
|
+
.and_raise(Vra::Http::Error.new('message', 404, 'Not Found'))
|
223
212
|
|
224
|
-
client.http_head('/404')
|
213
|
+
expect { client.http_head('/404') }.to raise_error(Vra::Exception::HTTPNotFound)
|
225
214
|
end
|
226
215
|
end
|
227
216
|
|
@@ -229,7 +218,7 @@ describe Vra::Client do
|
|
229
218
|
context 'when skip_auth is nil' do
|
230
219
|
it 'authorizes before proceeding' do
|
231
220
|
response = double('response')
|
232
|
-
allow(
|
221
|
+
allow(Vra::Http).to receive(:execute).and_return(response)
|
233
222
|
expect(client).to receive(:authorize!)
|
234
223
|
|
235
224
|
client.http_get('/test')
|
@@ -239,14 +228,14 @@ describe Vra::Client do
|
|
239
228
|
context 'when skip_auth is not nil' do
|
240
229
|
it 'does not authorize before proceeding' do
|
241
230
|
response = double('response')
|
242
|
-
allow(
|
231
|
+
allow(Vra::Http).to receive(:execute).and_return(response)
|
243
232
|
expect(client).to_not receive(:authorize!)
|
244
233
|
|
245
234
|
client.http_get('/test', :skip_auth)
|
246
235
|
end
|
247
236
|
end
|
248
237
|
|
249
|
-
it 'calls
|
238
|
+
it 'calls Vra::Http.execute' do
|
250
239
|
response = double('response')
|
251
240
|
path = '/test'
|
252
241
|
full_url = 'https://vra.corp.local/test'
|
@@ -254,79 +243,70 @@ describe Vra::Client do
|
|
254
243
|
verify_ssl = true
|
255
244
|
|
256
245
|
allow(client).to receive(:authorize!)
|
257
|
-
expect(
|
258
|
-
|
259
|
-
|
260
|
-
|
246
|
+
expect(Vra::Http).to receive(:execute).with(method: :get,
|
247
|
+
url: full_url,
|
248
|
+
headers: headers,
|
249
|
+
verify_ssl: verify_ssl)
|
261
250
|
.and_return(response)
|
262
251
|
|
263
252
|
client.http_get(path)
|
264
253
|
end
|
265
254
|
|
266
|
-
it '
|
255
|
+
it 'raises an HTTPNotFound on a 404 error' do
|
267
256
|
allow(client).to receive(:authorize!)
|
268
|
-
allow(
|
269
|
-
|
270
|
-
|
271
|
-
client.http_get('/404')
|
272
|
-
end
|
273
|
-
end
|
274
|
-
|
275
|
-
describe '#http_get!' do
|
276
|
-
it 'returns the response body' do
|
277
|
-
response = double('response', body: 'body text')
|
278
|
-
allow(client).to receive(:http_get).with('/test').and_return(response)
|
257
|
+
allow(Vra::Http).to receive(:execute)
|
258
|
+
.and_raise(Vra::Http::Error.new('message', 404, 'Not Found'))
|
279
259
|
|
280
|
-
expect
|
260
|
+
expect { client.http_get('/404') }.to raise_error(Vra::Exception::HTTPNotFound)
|
281
261
|
end
|
282
262
|
end
|
283
263
|
|
284
264
|
describe '#http_get_paginated_array!' do
|
285
265
|
it 'allows a limit override' do
|
286
266
|
client.page_size = 10
|
287
|
-
expect(client).to receive(:
|
267
|
+
expect(client).to receive(:get_parsed)
|
288
268
|
.with('/test?limit=10&page=1')
|
289
|
-
.and_return(
|
269
|
+
.and_return('content' => [], 'metadata' => { 'totalPages' => 1 })
|
290
270
|
|
291
271
|
client.http_get_paginated_array!('/test')
|
292
272
|
end
|
293
273
|
|
294
|
-
it 'only calls
|
295
|
-
expect(client).to receive(:
|
274
|
+
it 'only calls get_parsed once when total pages is 0 (no items)' do
|
275
|
+
expect(client).to receive(:get_parsed)
|
296
276
|
.once
|
297
277
|
.with('/test?limit=20&page=1')
|
298
|
-
.and_return(
|
278
|
+
.and_return('content' => [], 'metadata' => { 'totalPages' => 0 })
|
299
279
|
|
300
280
|
client.http_get_paginated_array!('/test')
|
301
281
|
end
|
302
282
|
|
303
|
-
it 'only calls
|
304
|
-
expect(client).to receive(:
|
283
|
+
it 'only calls get_parsed once when total pages is 1' do
|
284
|
+
expect(client).to receive(:get_parsed)
|
305
285
|
.once
|
306
286
|
.with('/test?limit=20&page=1')
|
307
|
-
.and_return(
|
287
|
+
.and_return('content' => [], 'metadata' => { 'totalPages' => 1 })
|
308
288
|
|
309
289
|
client.http_get_paginated_array!('/test')
|
310
290
|
end
|
311
291
|
|
312
|
-
it 'calls
|
313
|
-
expect(client).to receive(:
|
292
|
+
it 'calls get_parsed 3 times if there are 3 pages of response' do
|
293
|
+
expect(client).to receive(:get_parsed)
|
314
294
|
.with('/test?limit=20&page=1')
|
315
|
-
.and_return(
|
316
|
-
expect(client).to receive(:
|
295
|
+
.and_return('content' => [], 'metadata' => { 'totalPages' => 3 })
|
296
|
+
expect(client).to receive(:get_parsed)
|
317
297
|
.with('/test?limit=20&page=2')
|
318
|
-
.and_return(
|
319
|
-
expect(client).to receive(:
|
298
|
+
.and_return('content' => [], 'metadata' => { 'totalPages' => 3 })
|
299
|
+
expect(client).to receive(:get_parsed)
|
320
300
|
.with('/test?limit=20&page=3')
|
321
|
-
.and_return(
|
301
|
+
.and_return('content' => [], 'metadata' => { 'totalPages' => 3 })
|
322
302
|
|
323
303
|
client.http_get_paginated_array!('/test')
|
324
304
|
end
|
325
305
|
|
326
306
|
it 'raises an exception if duplicate items are returned by the API' do
|
327
|
-
allow(client).to receive(:
|
307
|
+
allow(client).to receive(:get_parsed)
|
328
308
|
.with('/test?limit=20&page=1')
|
329
|
-
.and_return(
|
309
|
+
.and_return('content' => [ 1, 2, 3, 1 ], 'metadata' => { 'totalPages' => 1 })
|
330
310
|
|
331
311
|
expect { client.http_get_paginated_array!('/test') }.to raise_error(Vra::Exception::DuplicateItemsDetected)
|
332
312
|
end
|
@@ -336,7 +316,7 @@ describe Vra::Client do
|
|
336
316
|
context 'when skip_auth is nil' do
|
337
317
|
it 'authorizes before proceeding' do
|
338
318
|
response = double('response')
|
339
|
-
allow(
|
319
|
+
allow(Vra::Http).to receive(:execute).and_return(response)
|
340
320
|
expect(client).to receive(:authorize!)
|
341
321
|
|
342
322
|
client.http_post('/test', 'some payload')
|
@@ -346,14 +326,14 @@ describe Vra::Client do
|
|
346
326
|
context 'when skip_auth is not nil' do
|
347
327
|
it 'does not authorize before proceeding' do
|
348
328
|
response = double('response')
|
349
|
-
allow(
|
329
|
+
allow(Vra::Http).to receive(:execute).and_return(response)
|
350
330
|
expect(client).to_not receive(:authorize!)
|
351
331
|
|
352
332
|
client.http_post('/test', 'some payload', :skip_auth)
|
353
333
|
end
|
354
334
|
end
|
355
335
|
|
356
|
-
it 'calls
|
336
|
+
it 'calls Vra::Http.execute' do
|
357
337
|
response = double('response')
|
358
338
|
path = '/test'
|
359
339
|
full_url = 'https://vra.corp.local/test'
|
@@ -362,19 +342,19 @@ describe Vra::Client do
|
|
362
342
|
verify_ssl = true
|
363
343
|
|
364
344
|
allow(client).to receive(:authorize!)
|
365
|
-
expect(
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
345
|
+
expect(Vra::Http).to receive(:execute).with(method: :post,
|
346
|
+
url: full_url,
|
347
|
+
headers: headers,
|
348
|
+
payload: payload,
|
349
|
+
verify_ssl: verify_ssl)
|
370
350
|
.and_return(response)
|
371
351
|
|
372
352
|
client.http_post(path, payload)
|
373
353
|
end
|
374
354
|
|
375
|
-
it 'calls raise_http_exception upon
|
355
|
+
it 'calls raise_http_exception upon error' do
|
376
356
|
allow(client).to receive(:authorize!)
|
377
|
-
allow(
|
357
|
+
allow(Vra::Http).to receive(:execute).and_raise(StandardError)
|
378
358
|
expect(client).to receive(:raise_http_exception)
|
379
359
|
|
380
360
|
client.http_post('/404', 'test payload')
|
data/spec/http_spec.rb
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'webmock'
|
3
|
+
|
4
|
+
describe Vra::Http do
|
5
|
+
def expecting_request(method, url, with=nil)
|
6
|
+
stub = stub_request(method, url)
|
7
|
+
stub.with(with) if with
|
8
|
+
yield if block_given?
|
9
|
+
expect(stub).to have_been_requested
|
10
|
+
end
|
11
|
+
|
12
|
+
def execute(method, params)
|
13
|
+
Vra::Http.execute(params.merge(method: method))
|
14
|
+
end
|
15
|
+
|
16
|
+
def get(params)
|
17
|
+
execute :get, params
|
18
|
+
end
|
19
|
+
|
20
|
+
def post(params)
|
21
|
+
execute :post, params
|
22
|
+
end
|
23
|
+
|
24
|
+
def head(params)
|
25
|
+
execute :head, params
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#execute' do
|
29
|
+
it 'makes a HEAD request' do
|
30
|
+
headers = { 'X-Made-Up-Header' => 'Foo AND bar? Are you sure?' }
|
31
|
+
|
32
|
+
expecting_request(:head, 'http://test.local', headers: headers) do
|
33
|
+
head url: 'http://test.local', headers: headers
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'makes a GET request' do
|
38
|
+
headers = { 'X-Made-Up-Header' => 'Foo AND bar? Are you sure?' }
|
39
|
+
|
40
|
+
expecting_request(:get, 'http://test.local', headers: headers) do
|
41
|
+
get url: 'http://test.local', headers: headers
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'makes a POST request' do
|
46
|
+
headers = { 'X-Made-Up-Header' => 'Foo AND bar? Are you sure?' }
|
47
|
+
payload = 'withabodylikethis'
|
48
|
+
|
49
|
+
expecting_request(:post, 'http://test.local', headers: headers, body: payload) do
|
50
|
+
post url: 'http://test.local', headers: headers, payload: payload
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'preserves Location' do
|
55
|
+
stub_request(:head, 'http://test.local')
|
56
|
+
.to_return(headers: { 'Location' => 'http://test-location.local' })
|
57
|
+
|
58
|
+
response = head(url: 'http://test.local')
|
59
|
+
|
60
|
+
expect(response.location).to eq 'http://test-location.local'
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'preserves status code' do
|
64
|
+
stub_request(:head, 'http://test.local')
|
65
|
+
.to_return(status: [204, 'No content'])
|
66
|
+
|
67
|
+
response = head(url: 'http://test.local')
|
68
|
+
|
69
|
+
expect(response.code).to eq 204
|
70
|
+
end
|
71
|
+
|
72
|
+
context 'when successful' do
|
73
|
+
it 'returns a successful response given a status 200' do
|
74
|
+
stub_request(:head, 'http://test.local')
|
75
|
+
.to_return(status: [200, 'Whatevs'])
|
76
|
+
|
77
|
+
response = head(url: 'http://test.local')
|
78
|
+
|
79
|
+
expect(response.success_ok?).to be_truthy
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'returns a successful response given a status 204' do
|
83
|
+
stub_request(:head, 'http://test.local')
|
84
|
+
.to_return(status: [204, 'Whatevs'])
|
85
|
+
|
86
|
+
response = head(url: 'http://test.local')
|
87
|
+
|
88
|
+
expect(response.success_no_content?).to be_truthy
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
context 'when unsuccessful' do
|
93
|
+
(400..418).each do |status|
|
94
|
+
it 'raises an exception given a status #{status}' do
|
95
|
+
stub_request(:get, 'http://test.local')
|
96
|
+
.to_return(status: [status, 'Whatevs'],
|
97
|
+
body: 'Error body')
|
98
|
+
|
99
|
+
expect { get(url: 'http://test.local') }.to raise_error do |error|
|
100
|
+
expect(error).to be_a(StandardError)
|
101
|
+
expect(error.http_code).to eq status
|
102
|
+
expect(error.response).to eq 'Error body'
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context 'when redirected' do
|
109
|
+
[301, 302, 307].each do |status|
|
110
|
+
[:get, :head].each do |method|
|
111
|
+
it "follows #{status} redirected #{method.to_s.upcase} requests" do
|
112
|
+
stub_request(method, 'http://test.local')
|
113
|
+
.to_return(status: [status, 'redirect'],
|
114
|
+
headers: { 'Location' => 'http://test.local/redirect' })
|
115
|
+
expecting_request(method, 'http://test.local/redirect') do
|
116
|
+
execute(method, url: 'http://test.local')
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
it "does not follow #{status} redirected POST requests" do
|
122
|
+
stub_request(:post, 'http://test.local')
|
123
|
+
.to_return(status: [status, 'redirect'],
|
124
|
+
headers: { 'Location' => 'http://test.local/redirect' })
|
125
|
+
|
126
|
+
expect { post(url: 'http://test.local') }.to raise_error do |error|
|
127
|
+
expect(error).to be_a(StandardError)
|
128
|
+
expect(error.http_code).to eq status
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
[:head, :post].each do |method|
|
134
|
+
it "converts #{method.to_s.upcase} to GET on 303 redirect" do
|
135
|
+
stub_request(method, 'http://test.local')
|
136
|
+
.to_return(status: [303, 'See Other'],
|
137
|
+
headers: { 'Location' => 'http://test.local/redirect' })
|
138
|
+
|
139
|
+
expecting_request(:get, 'http://test.local/redirect') do
|
140
|
+
execute method, url: 'http://test.local'
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
data/spec/request_spec.rb
CHANGED
@@ -71,9 +71,9 @@ describe Vra::Request do
|
|
71
71
|
|
72
72
|
describe '#refresh' do
|
73
73
|
it 'calls the request API endpoint' do
|
74
|
-
expect(client).to receive(:
|
74
|
+
expect(client).to receive(:get_parsed)
|
75
75
|
.with("/catalog-service/api/consumer/requests/#{request_id}")
|
76
|
-
.and_return(in_progress_payload
|
76
|
+
.and_return(in_progress_payload)
|
77
77
|
|
78
78
|
request.refresh
|
79
79
|
end
|
data/spec/resource_spec.rb
CHANGED
@@ -92,10 +92,10 @@ describe Vra::Resource do
|
|
92
92
|
end
|
93
93
|
|
94
94
|
describe '#fetch_resource_data' do
|
95
|
-
it 'calls
|
96
|
-
expect(client).to receive(:
|
95
|
+
it 'calls get_parsed against the resources API endpoint' do
|
96
|
+
expect(client).to receive(:get_parsed)
|
97
97
|
.with("/catalog-service/api/consumer/resources/#{resource_id}")
|
98
|
-
.and_return(
|
98
|
+
.and_return({})
|
99
99
|
|
100
100
|
Vra::Resource.new(client, id: resource_id)
|
101
101
|
end
|
@@ -356,7 +356,7 @@ describe Vra::Resource do
|
|
356
356
|
describe '#submit_action_request' do
|
357
357
|
before do
|
358
358
|
allow(resource).to receive(:action_request_payload).and_return({})
|
359
|
-
response = double('response',
|
359
|
+
response = double('response', location: '/requests/request-12345')
|
360
360
|
allow(client).to receive(:http_post).with('/catalog-service/api/consumer/requests', '{}').and_return(response)
|
361
361
|
end
|
362
362
|
|
data/vmware-vra.gemspec
CHANGED
@@ -18,7 +18,6 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ['lib']
|
20
20
|
|
21
|
-
spec.add_dependency 'rest-client', '~> 1.8'
|
22
21
|
spec.add_dependency 'ffi-yajl', '~> 2.2'
|
23
22
|
spec.add_dependency 'passwordmasker', '~> 1.2'
|
24
23
|
|
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vmware-vra
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adam Leff
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-05-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: rest-client
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '1.8'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - "~>"
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '1.8'
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: ffi-yajl
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -157,6 +143,7 @@ files:
|
|
157
143
|
- lib/vra/catalog_request.rb
|
158
144
|
- lib/vra/client.rb
|
159
145
|
- lib/vra/exceptions.rb
|
146
|
+
- lib/vra/http.rb
|
160
147
|
- lib/vra/request.rb
|
161
148
|
- lib/vra/request_parameters.rb
|
162
149
|
- lib/vra/requests.rb
|
@@ -170,6 +157,7 @@ files:
|
|
170
157
|
- spec/fixtures/resource/non_vm_resource.json
|
171
158
|
- spec/fixtures/resource/vm_resource.json
|
172
159
|
- spec/fixtures/resource/vm_resource_no_operations.json
|
160
|
+
- spec/http_spec.rb
|
173
161
|
- spec/request_spec.rb
|
174
162
|
- spec/requests_spec.rb
|
175
163
|
- spec/resource_spec.rb
|
@@ -196,7 +184,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
196
184
|
version: '0'
|
197
185
|
requirements: []
|
198
186
|
rubyforge_project:
|
199
|
-
rubygems_version: 2.
|
187
|
+
rubygems_version: 2.2.2
|
200
188
|
signing_key:
|
201
189
|
specification_version: 4
|
202
190
|
summary: Client gem for interacting with VMware vRealize Automation.
|
@@ -208,6 +196,7 @@ test_files:
|
|
208
196
|
- spec/fixtures/resource/non_vm_resource.json
|
209
197
|
- spec/fixtures/resource/vm_resource.json
|
210
198
|
- spec/fixtures/resource/vm_resource_no_operations.json
|
199
|
+
- spec/http_spec.rb
|
211
200
|
- spec/request_spec.rb
|
212
201
|
- spec/requests_spec.rb
|
213
202
|
- spec/resource_spec.rb
|