kitchen-vra 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -0
- data/README.md +17 -1
- data/lib/kitchen/driver/vra.rb +37 -12
- data/lib/kitchen/driver/vra_version.rb +1 -1
- data/spec/vra_spec.rb +97 -28
- 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: 5c7f119529c9a3562d45db721bf394fd9742d3a5
|
4
|
+
data.tar.gz: 7b2578c10fe9bfe7ed5d736c5b0ff0bd4de5cf7b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 073bbc3ed64031fb0e99fed859c4211362c354db494d0d21dec266f5039146c911d7fd72d33fb95dab34afaf0860ba9bd8b570ef55046077981e463fa0759dff
|
7
|
+
data.tar.gz: f8d23dbce4ad8a4c92b9ae42314063237c7149fce5f27c59db918a8d7046aa0baa8a0b470c956f1f87d30fe911fecd6d1b934946625ef7fd4c6b0a8516a3e235
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
# kitchen-vra Changelog
|
2
2
|
|
3
|
+
## v1.2.0 (2015-11-25)
|
4
|
+
* [pr#7](https://github.com/chef-partners/kitchen-vra/pull/7) Added retry logic for wait_until_ready in cases where Test Kitchen would unwind (such as DNS issues). Added fallback logic for when a host has no IP address, complimenting the `use_dns` parameter.
|
5
|
+
|
3
6
|
## v1.1.0 (2015-10-13)
|
4
7
|
* New `use_dns` option (defaults to false) for the driver to use the server name instead of the IP address - thanks to @stevehedrick in PR [#3](https://github.com/chef-partners/kitchen-vra/pull/3)
|
5
8
|
|
data/README.md
CHANGED
@@ -52,12 +52,14 @@ Other options that you can set include:
|
|
52
52
|
|
53
53
|
* **lease_days**: number of days to request for a lease, if your catalog item / blueprint requires it
|
54
54
|
* **request_timeout**: amount of time, in seconds, to wait for a vRA request to complete. Default is 600 seconds.
|
55
|
+
* **server_ready_retries**: Number of times to retry the "waiting for server to be ready" check. In some cases, this will error out immediately due to DNS propagation issues, etc. Setting this to a number greater than 0 will retry the `wait_until_ready` method with a growing sleep in between each attempt. Defaults to 1. Set to 0 to disable any retrying of the `wait_until_ready` method.
|
55
56
|
* **cpus**: number of CPUs the host should have
|
56
57
|
* **memory**: amount of RAM, in MB, the host should have
|
57
58
|
* **requested_for**: the vRA login ID to list as the owner of this resource. Defaults to the vRA username configured in the `driver` section.
|
58
59
|
* **subtenant_id**: the Business Group ID to list as the owner. This is required if the catalog item is a shared/global item; we are unable to determine the subtenant_id from the catalog, and vRA requires it to be set on every request.
|
59
|
-
* **private_key_path**: path to the SSH private key to use when logging in. Defaults to '~/.ssh/id_rsa' or '~/.ssh/id_dsa', preferring the RSA key. Only applies to instances where SSH transport is used
|
60
|
+
* **private_key_path**: path to the SSH private key to use when logging in. Defaults to '~/.ssh/id_rsa' or '~/.ssh/id_dsa', preferring the RSA key. Only applies to instances where SSH transport is used; i.e., does not apply to Windows hosts with the WinRM transport configured.
|
60
61
|
* **use_dns**: Defaults to `false`. Set to `true` if vRA doesn't manage vm ip addresses. This will cause kitchen to attempt to connect via hostname.
|
62
|
+
* **extra_parameters**: a hash of other data to set on a catalog request, most notably custom properties. Allows updates to existing properties on the blueprint as well as the addition of new properties. The vRA REST API expects 'provider-' appended to the front of a property name; each key in the hash is the property name, and the value is a another hash containing the value data type and the value itself.
|
61
63
|
|
62
64
|
These settings can be set globally under the top-level `driver` section, or they can be set on each platform, which allows you to set globals and then override them. For example, this configuration would set the CPU count to 1 except on the "large" platform:
|
63
65
|
|
@@ -70,10 +72,24 @@ platforms:
|
|
70
72
|
- name: small
|
71
73
|
driver:
|
72
74
|
catalog_id: 8a189191-fea6-43eb-981e-ee0fa40f8f57
|
75
|
+
extra_parameters:
|
76
|
+
provider-mycustompropname:
|
77
|
+
type: string
|
78
|
+
value: smallvalue
|
79
|
+
provider-Vrm.DataCenter.Location:
|
80
|
+
type: string
|
81
|
+
value: Non-Prod
|
73
82
|
- name: large
|
74
83
|
driver:
|
75
84
|
catalog_id: 1d7c6122-18fa-4ed6-bd13-8a33b6c6ed50
|
76
85
|
cpus: 2
|
86
|
+
extra_parameters:
|
87
|
+
provider-mycustompropname:
|
88
|
+
type: string
|
89
|
+
value: largevalue
|
90
|
+
provider-Vrm.DataCenter.Location:
|
91
|
+
type: string
|
92
|
+
value: Prod
|
77
93
|
```
|
78
94
|
|
79
95
|
## License and Authors
|
data/lib/kitchen/driver/vra.rb
CHANGED
@@ -22,7 +22,7 @@ require_relative 'vra_version'
|
|
22
22
|
|
23
23
|
module Kitchen
|
24
24
|
module Driver
|
25
|
-
class Vra < Kitchen::Driver::Base
|
25
|
+
class Vra < Kitchen::Driver::Base # rubocop:disable Metrics/ClassLength
|
26
26
|
kitchen_driver_api_version 2
|
27
27
|
plugin_version Kitchen::Driver::VRA_VERSION
|
28
28
|
|
@@ -36,6 +36,7 @@ module Kitchen
|
|
36
36
|
default_config :verify_ssl, true
|
37
37
|
default_config :request_timeout, 600
|
38
38
|
default_config :request_refresh_rate, 2
|
39
|
+
default_config :server_ready_retries, 1
|
39
40
|
default_config :cpus, 1
|
40
41
|
default_config :memory, 1024
|
41
42
|
default_config :requested_for do |driver|
|
@@ -61,17 +62,26 @@ module Kitchen
|
|
61
62
|
|
62
63
|
server = request_server
|
63
64
|
state[:resource_id] = server.id
|
65
|
+
state[:hostname] = hostname_for(server)
|
66
|
+
state[:ssh_key] = config[:private_key_path] unless config[:private_key_path].nil?
|
67
|
+
|
68
|
+
wait_for_server(state, server)
|
69
|
+
info("Server #{server.id} (#{server.name}) ready.")
|
70
|
+
end
|
71
|
+
|
72
|
+
def hostname_for(server)
|
64
73
|
if config[:use_dns]
|
65
74
|
raise 'No server name returned for the vRA request' if server.name.nil?
|
66
|
-
|
67
|
-
else
|
68
|
-
raise 'No IP address returned for the vRA request' if server.ip_addresses.first.nil?
|
69
|
-
state[:hostname] = server.ip_addresses.first
|
75
|
+
return server.name
|
70
76
|
end
|
71
|
-
state[:ssh_key] = config[:private_key_path] unless config[:private_key_path].nil?
|
72
77
|
|
73
|
-
|
74
|
-
|
78
|
+
ip_address = server.ip_addresses.first
|
79
|
+
if ip_address.nil?
|
80
|
+
warn("Server #{server.id} has no IP address. Falling back to server name (#{server.name})...")
|
81
|
+
server.name
|
82
|
+
else
|
83
|
+
ip_address
|
84
|
+
end
|
75
85
|
end
|
76
86
|
|
77
87
|
def request_server
|
@@ -91,12 +101,27 @@ module Kitchen
|
|
91
101
|
|
92
102
|
def wait_for_server(state, server)
|
93
103
|
info("Server #{server.id} (#{server.name}) created. Waiting until ready...")
|
104
|
+
|
105
|
+
try = 0
|
106
|
+
sleep_time = 1
|
107
|
+
|
94
108
|
begin
|
95
109
|
instance.transport.connection(state).wait_until_ready
|
96
|
-
rescue
|
97
|
-
|
98
|
-
|
99
|
-
|
110
|
+
rescue => e
|
111
|
+
warn("Server #{server.id} (#{server.name}) not reachable: #{e.class} -- #{e.message}")
|
112
|
+
|
113
|
+
try += 1
|
114
|
+
sleep_time *= 2
|
115
|
+
|
116
|
+
if try > config[:server_ready_retries]
|
117
|
+
error('Retries exceeded. Destroying server...')
|
118
|
+
destroy(state)
|
119
|
+
raise
|
120
|
+
else
|
121
|
+
warn("Sleeping #{sleep_time} seconds and retrying...")
|
122
|
+
sleep sleep_time
|
123
|
+
retry
|
124
|
+
end
|
100
125
|
end
|
101
126
|
end
|
102
127
|
|
data/spec/vra_spec.rb
CHANGED
@@ -103,28 +103,10 @@ describe Kitchen::Driver::Vra do
|
|
103
103
|
expect(state[:resource_id]).to eq('e8706351-cf4c-4c12-acb7-c90cc683b22c')
|
104
104
|
end
|
105
105
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
allow(resource).to receive(:name).and_return(nil)
|
111
|
-
expect { driver.create(state) }.to raise_error(RuntimeError)
|
112
|
-
end
|
113
|
-
it 'uses the server name as the hostname' do
|
114
|
-
driver.create(state)
|
115
|
-
expect(state[:hostname]).to eq('server1')
|
116
|
-
end
|
117
|
-
end
|
118
|
-
context 'when use_dns is false' do
|
119
|
-
it 'raises an exception if no IP address is available' do
|
120
|
-
allow(resource).to receive(:ip_addresses).and_return([])
|
121
|
-
expect { driver.create(state) }.to raise_error(RuntimeError)
|
122
|
-
end
|
123
|
-
it 'uses the IP address as the hostname' do
|
124
|
-
driver.create(state)
|
125
|
-
expect(state[:hostname]).to eq('1.2.3.4')
|
126
|
-
end
|
127
|
-
end
|
106
|
+
it 'sets the hostname in the state hash' do
|
107
|
+
allow(driver).to receive(:hostname_for).and_return('test_hostname')
|
108
|
+
driver.create(state)
|
109
|
+
expect(state[:hostname]).to eq('test_hostname')
|
128
110
|
end
|
129
111
|
|
130
112
|
it 'waits for the server to be ready' do
|
@@ -133,6 +115,41 @@ describe Kitchen::Driver::Vra do
|
|
133
115
|
end
|
134
116
|
end
|
135
117
|
|
118
|
+
describe '#hostname_for' do
|
119
|
+
let(:server) do
|
120
|
+
double('server',
|
121
|
+
id: 'test_id',
|
122
|
+
name: 'test_hostname',
|
123
|
+
ip_addresses: [ '1.2.3.4' ],
|
124
|
+
vm?: true)
|
125
|
+
end
|
126
|
+
|
127
|
+
context 'when use_dns is true' do
|
128
|
+
let(:config) { { use_dns: true } }
|
129
|
+
|
130
|
+
it 'raises an exception if the server name is nil' do
|
131
|
+
allow(server).to receive(:name).and_return(nil)
|
132
|
+
expect { driver.hostname_for(server) }.to raise_error(RuntimeError)
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'returns the server name' do
|
136
|
+
expect(driver.hostname_for(server)).to eq('test_hostname')
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
context 'when use_dns is false' do
|
141
|
+
it 'falls back to the server name if no IP address exists' do
|
142
|
+
allow(server).to receive(:ip_addresses).and_return([])
|
143
|
+
expect(driver).to receive(:warn)
|
144
|
+
expect(driver.hostname_for(server)).to eq('test_hostname')
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'returns the IP address if it exists' do
|
148
|
+
expect(driver.hostname_for(server)).to eq('1.2.3.4')
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
136
153
|
describe '#request_server' do
|
137
154
|
let(:submitted_request) { double('submitted_request') }
|
138
155
|
let(:catalog_request) { double('catalog_request') }
|
@@ -204,12 +221,12 @@ describe Kitchen::Driver::Vra do
|
|
204
221
|
end
|
205
222
|
end
|
206
223
|
|
207
|
-
describe '#
|
224
|
+
describe '#wait_for_server' do
|
208
225
|
let(:connection) { instance.transport.connection(state) }
|
209
226
|
let(:state) { {} }
|
210
227
|
let(:resource1) do
|
211
228
|
double('server1',
|
212
|
-
id: '
|
229
|
+
id: 'test_id',
|
213
230
|
name: 'server1',
|
214
231
|
ip_addresses: [ '1.2.3.4' ],
|
215
232
|
vm?: true)
|
@@ -217,6 +234,9 @@ describe Kitchen::Driver::Vra do
|
|
217
234
|
|
218
235
|
before do
|
219
236
|
allow(transport).to receive(:connection).and_return(connection)
|
237
|
+
allow(driver).to receive(:sleep)
|
238
|
+
allow(driver).to receive(:warn)
|
239
|
+
allow(driver).to receive(:error)
|
220
240
|
end
|
221
241
|
|
222
242
|
it 'waits for the server to be ready' do
|
@@ -224,10 +244,59 @@ describe Kitchen::Driver::Vra do
|
|
224
244
|
driver.wait_for_server(state, resource1)
|
225
245
|
end
|
226
246
|
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
247
|
+
context 'when an exception is caught and retries is 0' do
|
248
|
+
let(:config) { { server_ready_retries: 0 } }
|
249
|
+
|
250
|
+
it 'does not sleep and raises an exception' do
|
251
|
+
allow(connection).to receive(:wait_until_ready).and_raise(Timeout::Error)
|
252
|
+
expect(driver).not_to receive(:sleep)
|
253
|
+
expect(driver).to receive(:error).with('Retries exceeded. Destroying server...')
|
254
|
+
expect { driver.wait_for_server(state, resource1) }.to raise_error(Timeout::Error)
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
context 'when retries is 1 and it errors out twice' do
|
259
|
+
let(:config) { { server_ready_retries: 1 } }
|
260
|
+
|
261
|
+
it 'displays a warning, sleeps once, retries, errors, destroys, and raises' do
|
262
|
+
expect(connection).to receive(:wait_until_ready).twice.and_raise(Timeout::Error)
|
263
|
+
expect(driver).to receive(:warn).once.with('Sleeping 2 seconds and retrying...')
|
264
|
+
expect(driver).to receive(:sleep).once.with(2)
|
265
|
+
expect(driver).to receive(:error).with('Retries exceeded. Destroying server...')
|
266
|
+
expect(driver).to receive(:destroy).with(state)
|
267
|
+
expect { driver.wait_for_server(state, resource1) }.to raise_error(Timeout::Error)
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
context 'when retries is 2 and it errors out all 3 times' do
|
272
|
+
let(:config) { { server_ready_retries: 2 } }
|
273
|
+
|
274
|
+
it 'displays 2 warnings, sleeps twice, retries, errors, destroys, and raises' do
|
275
|
+
expect(connection).to receive(:wait_until_ready).exactly(3).times.and_raise(Timeout::Error)
|
276
|
+
expect(driver).to receive(:warn).once.with('Sleeping 2 seconds and retrying...')
|
277
|
+
expect(driver).to receive(:warn).once.with('Sleeping 4 seconds and retrying...')
|
278
|
+
expect(driver).to receive(:sleep).once.with(2)
|
279
|
+
expect(driver).to receive(:sleep).once.with(4)
|
280
|
+
expect(driver).to receive(:error).with('Retries exceeded. Destroying server...')
|
281
|
+
expect(driver).to receive(:destroy).with(state)
|
282
|
+
expect { driver.wait_for_server(state, resource1) }.to raise_error(Timeout::Error)
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
context 'when retries is 5, it errors out the first 2 tries, but works on the 3rd' do
|
287
|
+
let(:config) { { server_ready_retries: 5 } }
|
288
|
+
|
289
|
+
it 'displays 2 warnings, sleeps twice, retries, but does not destroy or raise' do
|
290
|
+
expect(connection).to receive(:wait_until_ready).twice.and_raise(Timeout::Error)
|
291
|
+
expect(connection).to receive(:wait_until_ready).once.and_return(true)
|
292
|
+
expect(driver).to receive(:warn).once.with('Sleeping 2 seconds and retrying...')
|
293
|
+
expect(driver).to receive(:warn).once.with('Sleeping 4 seconds and retrying...')
|
294
|
+
expect(driver).to receive(:sleep).once.with(2)
|
295
|
+
expect(driver).to receive(:sleep).once.with(4)
|
296
|
+
expect(driver).not_to receive(:error)
|
297
|
+
expect(driver).not_to receive(:destroy)
|
298
|
+
expect { driver.wait_for_server(state, resource1) }.not_to raise_error
|
299
|
+
end
|
231
300
|
end
|
232
301
|
end
|
233
302
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kitchen-vra
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chef Partner Engineering
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-11-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: test-kitchen
|