vra-restapi 1.5.2

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.
@@ -0,0 +1,59 @@
1
+ #
2
+ # Author:: Chef Partner Engineering (<partnereng@chef.io>)
3
+ # Copyright:: Copyright (c) 2015 Chef Software, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'spec_helper'
20
+
21
+ describe Vra::Requests do
22
+ let(:client) do
23
+ Vra::Client.new(username: 'user@corp.local',
24
+ password: 'password',
25
+ tenant: 'tenant',
26
+ base_url: 'https://vra.corp.local')
27
+ end
28
+
29
+ let(:requests) { Vra::Requests.new(client) }
30
+
31
+ describe '#all_resources' do
32
+ it 'calls the requests API endpoint' do
33
+ expect(client).to receive(:http_get_paginated_array!)
34
+ .with('/catalog-service/api/consumer/requests')
35
+ .and_return([])
36
+
37
+ requests.all_requests
38
+ end
39
+
40
+ it 'returns an array of request objects' do
41
+ allow(client).to receive(:http_get_paginated_array!)
42
+ .with('/catalog-service/api/consumer/requests')
43
+ .and_return([ { 'id' => '1' }, { 'id' => '2' } ])
44
+
45
+ items = requests.all_requests
46
+
47
+ expect(items[0]).to be_an_instance_of(Vra::Request)
48
+ expect(items[1]).to be_an_instance_of(Vra::Request)
49
+ end
50
+ end
51
+
52
+ describe '#by_id' do
53
+ it 'returns a request object' do
54
+ expect(Vra::Request).to receive(:new).with(client, '12345')
55
+
56
+ requests.by_id('12345')
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,394 @@
1
+ #
2
+ # Author:: Chef Partner Engineering (<partnereng@chef.io>)
3
+ # Copyright:: Copyright (c) 2015 Chef Software, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'spec_helper'
20
+ require 'json'
21
+
22
+ shared_examples_for 'a resource action' do |action_method, action_name|
23
+ context 'when the action is available' do
24
+ it 'calls gets the action ID and submits the request' do
25
+ expect(resource).to receive(:action_id_by_name).with(action_name).and_return('action-123')
26
+ expect(resource).to receive(:submit_action_request).with('action-123')
27
+ resource.send(action_method)
28
+ end
29
+ end
30
+
31
+ context 'when the action is not available' do
32
+ it 'raises an exception' do
33
+ expect(resource).to receive(:action_id_by_name).with(action_name).and_return nil
34
+ expect { resource.send(action_method) }.to raise_error(Vra::Exception::NotFound)
35
+ end
36
+ end
37
+ end
38
+
39
+ describe Vra::Resource do
40
+ let(:client) do
41
+ Vra::Client.new(username: 'user@corp.local',
42
+ password: 'password',
43
+ tenant: 'tenant',
44
+ base_url: 'https://vra.corp.local')
45
+ end
46
+
47
+ let(:resource_id) { '31a7badc-6562-458d-84f3-ec58d74a6953' }
48
+ let(:vm_payload) do
49
+ JSON.parse(File.read(File.join(File.dirname(__FILE__),
50
+ 'fixtures',
51
+ 'resource',
52
+ 'vm_resource.json')))
53
+ end
54
+
55
+ let(:vm_payload_no_ops) do
56
+ JSON.parse(File.read(File.join(File.dirname(__FILE__),
57
+ 'fixtures',
58
+ 'resource',
59
+ 'vm_resource_no_operations.json')))
60
+ end
61
+
62
+ let(:non_vm_payload) do
63
+ JSON.parse(File.read(File.join(File.dirname(__FILE__),
64
+ 'fixtures',
65
+ 'resource',
66
+ 'non_vm_resource.json')))
67
+ end
68
+
69
+ describe '#initialize' do
70
+ it 'raises an error if no ID or resource data have been provided' do
71
+ expect { Vra::Resource.new }.to raise_error(ArgumentError)
72
+ end
73
+
74
+ it 'raises an error if an ID and resource data have both been provided' do
75
+ expect { Vra::Resource.new(id: 123, data: 'foo') }.to raise_error(ArgumentError)
76
+ end
77
+
78
+ context 'when an ID is provided' do
79
+ it 'calls fetch_resource_data' do
80
+ resource = Vra::Resource.allocate
81
+ expect(resource).to receive(:fetch_resource_data)
82
+ resource.send(:initialize, client, id: resource_id)
83
+ end
84
+ end
85
+
86
+ context 'when resource data is provided' do
87
+ it 'populates the ID correctly' do
88
+ resource = Vra::Resource.new(client, data: vm_payload)
89
+ expect(resource.id).to eq resource_id
90
+ end
91
+ end
92
+ end
93
+
94
+ describe '#fetch_resource_data' do
95
+ it 'calls http_get! against the resources API endpoint' do
96
+ expect(client).to receive(:http_get!)
97
+ .with("/catalog-service/api/consumer/resources/#{resource_id}")
98
+ .and_return("{}")
99
+
100
+ Vra::Resource.new(client, id: resource_id)
101
+ end
102
+ end
103
+
104
+ context 'when a valid VM resource instance has been created' do
105
+ let(:resource) { Vra::Resource.new(client, data: vm_payload) }
106
+
107
+ describe '#name' do
108
+ it 'returns the correct name' do
109
+ expect(resource.name).to eq 'hol-dev-11'
110
+ end
111
+ end
112
+
113
+ describe '#description' do
114
+ it 'returns the correct description' do
115
+ expect(resource.description).to eq 'test-description'
116
+ end
117
+ end
118
+
119
+ describe '#status' do
120
+ it 'returns the correct status' do
121
+ expect(resource.status).to eq 'ACTIVE'
122
+ end
123
+ end
124
+
125
+ describe '#vm?' do
126
+ context 'when the resource type is Infrastructure.Virtual' do
127
+ let(:resource_data) { { 'resourceTypeRef' => { 'id' => 'Infrastructure.Virtual' } } }
128
+ it 'returns true' do
129
+ allow(resource).to receive(:resource_data).and_return(resource_data)
130
+ expect(resource.vm?).to eq(true)
131
+ end
132
+ end
133
+
134
+ context 'when the resource type is Infrastructure.Cloud' do
135
+ let(:resource_data) { { 'resourceTypeRef' => { 'id' => 'Infrastructure.Cloud' } } }
136
+ it 'returns true' do
137
+ allow(resource).to receive(:resource_data).and_return(resource_data)
138
+ expect(resource.vm?).to eq(true)
139
+ end
140
+ end
141
+
142
+ context 'when the resource type is an unknown type' do
143
+ let(:resource_data) { { 'resourceTypeRef' => { 'id' => 'Infrastructure.Unknown' } } }
144
+ it 'returns false' do
145
+ allow(resource).to receive(:resource_data).and_return(resource_data)
146
+ expect(resource.vm?).to eq(false)
147
+ end
148
+ end
149
+ end
150
+
151
+ describe '#tenant_id' do
152
+ it 'returns the correct tenant ID' do
153
+ expect(resource.tenant_id).to eq 'vsphere.local'
154
+ end
155
+ end
156
+
157
+ describe '#tenant_name' do
158
+ it 'returns the correct tenant name' do
159
+ expect(resource.tenant_name).to eq 'vsphere.local'
160
+ end
161
+ end
162
+
163
+ describe '#subtenant_id' do
164
+ it 'returns the correct subtenant ID' do
165
+ expect(resource.subtenant_id).to eq '5327ddd3-1a4e-4663-9e9d-63db86ffc8af'
166
+ end
167
+ end
168
+
169
+ describe '#subtenant_name' do
170
+ it 'returns the correct subtenant name' do
171
+ expect(resource.subtenant_name).to eq 'Rainpole Developers'
172
+ end
173
+ end
174
+
175
+ describe '#owner_ids' do
176
+ it 'returns the correct owner IDs' do
177
+ expect(resource.owner_ids).to eq %w(user1@corp.local user2@corp.local)
178
+ end
179
+ end
180
+
181
+ describe '#owner_names' do
182
+ it 'returns the correct owner names' do
183
+ expect(resource.owner_names).to eq [ 'Joe User', 'Jane User' ]
184
+ end
185
+ end
186
+
187
+ describe '#machine_status' do
188
+ context 'when no MachineStatus exists' do
189
+ let(:resource_data) { { 'resourceData' => { 'entries' => [] } } }
190
+
191
+ it 'raises an exception' do
192
+ allow(resource).to receive(:resource_data).and_return(resource_data)
193
+ expect { resource.machine_status }.to raise_error(RuntimeError)
194
+ end
195
+ end
196
+
197
+ context 'when MachineStatus Exists' do
198
+ let(:resource_data) do
199
+ {
200
+ 'resourceData' => {
201
+ 'entries' => [
202
+ {
203
+ 'key' => 'MachineStatus',
204
+ 'value' => { 'type' => 'string', 'value' => 'Off' }
205
+ }
206
+ ]
207
+ }
208
+ }
209
+ end
210
+
211
+ it 'returns the correct status value' do
212
+ allow(resource).to receive(:resource_data).and_return(resource_data)
213
+ expect(resource.machine_status).to eq('Off')
214
+ end
215
+ end
216
+ end
217
+
218
+ describe '#machine_on?' do
219
+ it 'returns true if the machine_status is On' do
220
+ allow(resource).to receive(:machine_status).and_return('On')
221
+ expect(resource.machine_on?).to eq(true)
222
+ end
223
+
224
+ it 'returns false if the machine_status is not On' do
225
+ allow(resource).to receive(:machine_status).and_return('Off')
226
+ expect(resource.machine_on?).to eq(false)
227
+ end
228
+ end
229
+
230
+ describe '#machine_off?' do
231
+ it 'returns true if the machine_status is Off' do
232
+ allow(resource).to receive(:machine_status).and_return('Off')
233
+ expect(resource.machine_off?).to eq(true)
234
+ end
235
+
236
+ it 'returns false if the machine_status is not Off' do
237
+ allow(resource).to receive(:machine_status).and_return('On')
238
+ expect(resource.machine_off?).to eq(false)
239
+ end
240
+ end
241
+
242
+ describe '#machine_turning_on?' do
243
+ it 'returns true if the machine_status is TurningOn' do
244
+ allow(resource).to receive(:machine_status).and_return('TurningOn')
245
+ expect(resource.machine_turning_on?).to eq(true)
246
+ end
247
+
248
+ it 'returns true if the machine_status is MachineActivated' do
249
+ allow(resource).to receive(:machine_status).and_return('MachineActivated')
250
+ expect(resource.machine_turning_on?).to eq(true)
251
+ end
252
+
253
+ it 'returns false if the machine_status is not TurningOn' do
254
+ allow(resource).to receive(:machine_status).and_return('On')
255
+ expect(resource.machine_turning_on?).to eq(false)
256
+ end
257
+ end
258
+
259
+ describe '#machine_turning_off?' do
260
+ it 'returns true if the machine_status is TurningOff' do
261
+ allow(resource).to receive(:machine_status).and_return('TurningOff')
262
+ expect(resource.machine_turning_off?).to eq(true)
263
+ end
264
+
265
+ it 'returns true if the machine_status is ShuttingDown' do
266
+ allow(resource).to receive(:machine_status).and_return('ShuttingDown')
267
+ expect(resource.machine_turning_off?).to eq(true)
268
+ end
269
+
270
+ it 'returns false if the machine_status is not TurningOff or ShuttingDown' do
271
+ allow(resource).to receive(:machine_status).and_return('Off')
272
+ expect(resource.machine_turning_off?).to eq(false)
273
+ end
274
+ end
275
+
276
+ describe '#machine_in_provisioned_state?' do
277
+ it 'returns true if the machine_status is MachineProvisioned' do
278
+ allow(resource).to receive(:machine_status).and_return('MachineProvisioned')
279
+ expect(resource.machine_in_provisioned_state?).to eq(true)
280
+ end
281
+
282
+ it 'returns false if the machine_status is not MachineProvisioned' do
283
+ allow(resource).to receive(:machine_status).and_return('On')
284
+ expect(resource.machine_in_provisioned_state?).to eq(false)
285
+ end
286
+ end
287
+
288
+ describe '#network_interfaces' do
289
+ it 'returns an array of 2 elements' do
290
+ expect(resource.network_interfaces.size).to be 2
291
+ end
292
+
293
+ it 'contains the correct data' do
294
+ nic1, nic2 = resource.network_interfaces
295
+
296
+ expect(nic1['NETWORK_NAME']).to eq 'VM Network'
297
+ expect(nic1['NETWORK_ADDRESS']).to eq '192.168.110.200'
298
+ expect(nic1['NETWORK_MAC_ADDRESS']).to eq '00:50:56:ae:95:3c'
299
+
300
+ expect(nic2['NETWORK_NAME']).to eq 'Management Network'
301
+ expect(nic2['NETWORK_ADDRESS']).to eq '192.168.220.200'
302
+ expect(nic2['NETWORK_MAC_ADDRESS']).to eq '00:50:56:ae:95:3d'
303
+ end
304
+ end
305
+
306
+ describe '#ip_addresses' do
307
+ it 'returns the correct IP addresses' do
308
+ expect(resource.ip_addresses).to eq [ '192.168.110.200', '192.168.220.200' ]
309
+ end
310
+
311
+ it 'returns nil if there are no network interfaces' do
312
+ allow(resource).to receive(:network_interfaces).and_return nil
313
+ expect(resource.ip_addresses).to be_nil
314
+ end
315
+ end
316
+
317
+ describe '#actions' do
318
+ it 'does not call #fetch_resource_data' do
319
+ expect(resource).not_to receive(:fetch_resource_data)
320
+ resource.actions
321
+ end
322
+ end
323
+
324
+ describe '#action_id_by_name' do
325
+ it 'returns the correct action ID for the destroy action' do
326
+ expect(resource.action_id_by_name('Destroy')).to eq 'ace8ba42-e724-48d8-9614-9b3a62b5a464'
327
+ end
328
+
329
+ it 'returns nil if there are no resource operations' do
330
+ allow(resource).to receive(:actions).and_return nil
331
+ expect(resource.action_id_by_name('Destroy')).to be_nil
332
+ end
333
+
334
+ it 'returns nil if there are actions, but none with the right name' do
335
+ allow(resource).to receive(:actions).and_return([ { 'name' => 'some action' }, { 'name' => 'another action' } ])
336
+ expect(resource.action_id_by_name('Destroy')).to be_nil
337
+ end
338
+ end
339
+
340
+ describe '#destroy' do
341
+ it_behaves_like 'a resource action', :destroy, 'Destroy'
342
+ end
343
+
344
+ describe '#shutdown' do
345
+ it_behaves_like 'a resource action', :shutdown, 'Shutdown'
346
+ end
347
+
348
+ describe '#poweroff' do
349
+ it_behaves_like 'a resource action', :poweroff, 'Power Off'
350
+ end
351
+
352
+ describe '#poweron' do
353
+ it_behaves_like 'a resource action', :poweron, 'Power On'
354
+ end
355
+
356
+ describe '#submit_action_request' do
357
+ before do
358
+ allow(resource).to receive(:action_request_payload).and_return({})
359
+ response = double('response', code: 200, headers: { location: '/requests/request-12345' })
360
+ allow(client).to receive(:http_post).with('/catalog-service/api/consumer/requests', '{}').and_return(response)
361
+ end
362
+
363
+ it 'calls http_post' do
364
+ expect(client).to receive(:http_post).with('/catalog-service/api/consumer/requests', '{}')
365
+
366
+ resource.submit_action_request('action-123')
367
+ end
368
+
369
+ it 'returns a Vra::Request object' do
370
+ expect(resource.submit_action_request('action-123')).to be_an_instance_of(Vra::Request)
371
+ end
372
+ end
373
+ end
374
+
375
+ context 'when a valid VM resource instance with no operations is created' do
376
+ let(:resource) { Vra::Resource.new(client, data: vm_payload_no_ops) }
377
+
378
+ describe '#actions' do
379
+ it 'calls #fetch_resource_data' do
380
+ expect(resource).to receive(:fetch_resource_data)
381
+ resource.actions
382
+ end
383
+ end
384
+ end
385
+
386
+ context 'when a valid non-VM resource instance has been created' do
387
+ let(:resource) { Vra::Resource.new(client, data: non_vm_payload) }
388
+
389
+ it 'returns nil for network_interfaces and ip_addresses' do
390
+ expect(resource.network_interfaces).to be_nil
391
+ expect(resource.ip_addresses).to be_nil
392
+ end
393
+ end
394
+ end