rspec-system 2.5.1 → 2.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +24 -0
- data/README.md +66 -71
- data/lib/rspec-system.rb +0 -1
- data/lib/rspec-system/helper.rb +2 -5
- data/lib/rspec-system/helpers.rb +1 -1
- data/lib/rspec-system/helpers/rcp.rb +2 -5
- data/lib/rspec-system/helpers/shell.rb +1 -1
- data/lib/rspec-system/node.rb +1 -3
- data/lib/rspec-system/node_set.rb +12 -4
- data/lib/rspec-system/node_set/base.rb +132 -7
- data/lib/rspec-system/node_set/{vagrant.rb → vagrant_base.rb} +63 -82
- data/lib/rspec-system/node_set/vagrant_virtualbox.rb +41 -0
- data/lib/rspec-system/node_set/vagrant_vmware_fusion.rb +43 -0
- data/lib/rspec-system/node_set/vsphere.rb +35 -95
- data/lib/rspec-system/spec_helper.rb +50 -11
- data/resources/prefabs.yml +26 -116
- data/rspec-system.gemspec +4 -4
- data/spec/spec_helper_system.rb +0 -1
- data/spec/system/base_spec.rb +8 -2
- metadata +16 -31
- data/lib/rspec-system/internal_helpers.rb +0 -101
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 53c1e505cedc7e77105136f17ffce867f00fc007
|
4
|
+
data.tar.gz: 3bfff0443416ff446e1cdd14c5fb12c9eec6121e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c1da1f38adcf52f28afffd07ad06694e82b73afd17ae678786e5e4e166ea045d1f08951f22a0e9bbdba5b407c54f07e6c02c8a281a1c2535b476c8ea9b827634
|
7
|
+
data.tar.gz: 1e4fab285717d34a3e585bf172af018d1ddb9936c71c5e8859f997850746714acdd11c015775a52ad3db9bde2053390b2c50cae2dd203697644fe4773e658aeb
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,27 @@
|
|
1
|
+
2.6.0
|
2
|
+
=====
|
3
|
+
|
4
|
+
This is a feature release that improves a number of areas:
|
5
|
+
|
6
|
+
* Split out vagrant commonalities into a vagrant_base class
|
7
|
+
* Add support for vagrant-vmware_fusion
|
8
|
+
* Fix vagrant so we log in as root, not log in as vagrant and sudo
|
9
|
+
* Break out steps in providers: launch, connect, configure
|
10
|
+
* Generalise the SSH connection routines
|
11
|
+
* Provide a series of global configuration steps, like ntp sync, hostname
|
12
|
+
fixups etc.
|
13
|
+
* Deprecated the internal_helpers module, its better to avoid global
|
14
|
+
methods anyway
|
15
|
+
* Switched to using RS_ as the prefix for environment variables
|
16
|
+
|
17
|
+
#### Detailed Changes
|
18
|
+
|
19
|
+
* Refactor with some new features (Ken Barber)
|
20
|
+
* fix multi-node sample in readme (Pall Valmundsson)
|
21
|
+
* remove unnecessary if statment (Johan Haals)
|
22
|
+
|
23
|
+
-------------------------------
|
24
|
+
|
1
25
|
2.5.1
|
2
26
|
=====
|
3
27
|
|
data/README.md
CHANGED
@@ -123,8 +123,8 @@ In your `.nodeset.yml` file you will need to define multiple nodes:
|
|
123
123
|
---
|
124
124
|
sets:
|
125
125
|
'centos-59-x64-multinode':
|
126
|
+
default_node: 'first.mydomain.vm'
|
126
127
|
nodes:
|
127
|
-
default_node: 'first.mydomain.vm':
|
128
128
|
'first.mydomain.vm':
|
129
129
|
prefab: 'centos-59-x64'
|
130
130
|
'second.mydomain.vm':
|
@@ -203,7 +203,7 @@ To define custom prefabs place a `.prefabs.yml` file in your project's root dire
|
|
203
203
|
kernel: Linux
|
204
204
|
rubyversion: "1.8.7"
|
205
205
|
provider_specifics:
|
206
|
-
|
206
|
+
vagrant_virtualbox:
|
207
207
|
box: 'scientific-64-x64-vb4210-nocm'
|
208
208
|
box_url: 'http://example.com/path/to/scientific-64-x64-vb4210-nocm.box'
|
209
209
|
|
@@ -216,7 +216,7 @@ For example, to use a different box for CentOS 6.4 x64, you can override the `bo
|
|
216
216
|
---
|
217
217
|
'centos-64-x64':
|
218
218
|
provider_specifics:
|
219
|
-
|
219
|
+
vagrant_virtualbox:
|
220
220
|
box: 'centos-64-x64-vbox4210'
|
221
221
|
box_url: 'http://puppet-vagrant-boxes.puppetlabs.com/centos-64-x64-vbox4210.box'
|
222
222
|
|
@@ -229,7 +229,25 @@ There are two providers at the moment you can use to launch your nodes for testi
|
|
229
229
|
|
230
230
|
Although both systems can be used for either purpose, if you so desire.
|
231
231
|
|
232
|
-
|
232
|
+
Instead of switches, we use a number of environment variables to modify the behaviour of running tests. This is more inline with the way testing frameworks like Jenkins work, and should be pretty easy for command line users as well:
|
233
|
+
|
234
|
+
* *RS_PROVIDER* - defines the nodeset provider, for now `vagrant_virtualbox` is the default.
|
235
|
+
* *RS_SET* - the set to use when running tests (defaults to the `default_set` setting in the projects `.nodeset.yml` file). This string must align with the entries under `sets` in your `.nodeset.yml`.
|
236
|
+
* *RS_DESTROY* - set this to `no` if you do not want your nodes to be destroyed before or after a test completes. May be useful during initial testing of rspec tests to allow inspection of the node.
|
237
|
+
* *RS_TMP* - This patch is used for various temporary content. Default is the directory `.rspec_system` in your projects root.
|
238
|
+
* *RS_SSH_TRIES* - Number of attempts to connect to a node using SSH. Defaults to 10.
|
239
|
+
* *RS_SSH_SLEEP* - Number of seconds between attempts. Defaults to 4.
|
240
|
+
* *RS_SSH_TIMEOUT* - Timeout for attempting SSH connectivity. Defaults to 60.
|
241
|
+
|
242
|
+
So if you wanted to run an alternate nodeset you could use:
|
243
|
+
|
244
|
+
RS_SET=fedora18 bundle exec rake spec:system
|
245
|
+
|
246
|
+
In Jenkins you should be able to use RS\_SET in a test matrix, thus obtaining quite a nice integration and visual display of nodesets in Jenkins.
|
247
|
+
|
248
|
+
#### Vagrant Virtualbox
|
249
|
+
|
250
|
+
RS_PROVIDER='vagrant_virtualbox'
|
233
251
|
|
234
252
|
This is the default provider, as all the products for this provider are free, most people should be able to run it.
|
235
253
|
|
@@ -244,57 +262,49 @@ Once these are ready, you can Run the system tests with:
|
|
244
262
|
|
245
263
|
The VM's should be downloaded from the internet, started and tests should run.
|
246
264
|
|
247
|
-
|
265
|
+
#### Vagrant VMware Fusion
|
248
266
|
|
249
|
-
|
250
|
-
* *RSPEC_SET* - the set to use when running tests (defaults to the `default_set` setting in the projects `.nodeset.yml` file). This string must align with the entries under `sets` in your `.nodeset.yml`.
|
251
|
-
* *RSPEC_DESTROY* - set this to `no` if you do not want the VM to be destroyed before or after a test completes. May be useful during initial testing of rspec tests to allow inspection of the VM.
|
252
|
-
* *RSPEC_SYSTEM_TMP* - Sets the path to create vagrant_projects directory containing each Nodeset's Vagrantfile. Default is the directory `.rspec_system` in your projects root.
|
267
|
+
RS_PROVIDER='vagrant_vmware_fusion'
|
253
268
|
|
254
|
-
|
269
|
+
Make sure you have already installed:
|
255
270
|
|
256
|
-
|
271
|
+
* VirtualBox 4.2.10+
|
272
|
+
* VMware Fusion 5.0.3+
|
257
273
|
|
258
|
-
|
274
|
+
Once these are ready, you can Run the system tests with:
|
259
275
|
|
260
|
-
|
276
|
+
RS_PROVIDER='vagrant_vmware_fusion' bundle exec rake spec:system
|
261
277
|
|
262
|
-
|
278
|
+
The VM's should be downloaded from the internet, started and tests should run.
|
263
279
|
|
264
|
-
#### VSphere
|
280
|
+
#### VSphere
|
265
281
|
|
266
|
-
|
282
|
+
RS_PROVIDER='vsphere'
|
267
283
|
|
268
284
|
This provider will launch nodes using VMWare VSphere API's and use those for running tests. This provider is really aimed at the users who want to use this library within their own CI system for example, as apposed to developers who wish to run tests locally themselves.
|
269
285
|
|
270
286
|
This provider has a lot more options for setup, in the form of environment variables:
|
271
287
|
|
272
|
-
* *
|
273
|
-
* *
|
274
|
-
* *
|
275
|
-
* *
|
276
|
-
* *
|
277
|
-
* *
|
278
|
-
* *
|
279
|
-
* *
|
280
|
-
* *
|
281
|
-
* *
|
282
|
-
* *
|
283
|
-
* *
|
284
|
-
* *
|
285
|
-
* *
|
286
|
-
* *RSPEC_VSPHERE_NODE_SLEEP* - amount of seconds to sleep for before trying again. Defaults to a random number between 30 and 90.
|
287
|
-
* *RSPEC_VSPHERE_SSH_TIMEOUT* - amount of seconds before retrying to SSH into a node. Default to 60.
|
288
|
-
* *RSPEC_VSPHERE_SSH_TRIES* - amount of attempts to SSH into a node. Defaults to 10.
|
289
|
-
* *RSPEC_VSPHERE_SSH_SLEEP* - amount of seconds to sleep before trying to SSH again. Defaults to 4.
|
290
|
-
* *RSPEC_VSPHERE_CONNECT_TIMEOUT* - amount of seconds before retrying to connect to the VSphere API. Defaults to 60.
|
291
|
-
* *RSPEC_VSPHERE_CONNECT_TRIES* - amount of attempts to connect to the VSphere API. Defaults to 10.
|
292
|
-
|
293
|
-
Set these variables, and run the usual rake command:
|
288
|
+
* *RS_VSPHERE_HOST* - hostname of your vsphere api
|
289
|
+
* *RS_VSPHERE_USER* - username to authenticate with
|
290
|
+
* *RS_VSPHERE_PASS* - password to authenticate with
|
291
|
+
* *RS_VSPHERE_DEST_DIR* - destination path to launch vm's
|
292
|
+
* *RS_VSPHERE_TEMPLATE_DIR* - path to where you deployed the templates from the OVF files described above
|
293
|
+
* *RS_VSPHERE_RPOOL* - name of resource pool to use
|
294
|
+
* *RS_VSPHERE_CLUSTER* - name of the cluster to use
|
295
|
+
* *RS_VSPHERE_SSH_KEYS* - path to private key for authentication. Multiple paths may be provided using a colon separator.
|
296
|
+
* *RS_VSPHERE_DATACENTER* - optional name of VSphere data centre
|
297
|
+
* *RS_VSPHERE_NODE_TIMEOUT* - amount of seconds before trying to relaunch a node. Defaults to 1200.
|
298
|
+
* *RS_VSPHERE_NODE_TRIES* - amount of attempts to relaunch a node. Defaults to 10.
|
299
|
+
* *RS_VSPHERE_NODE_SLEEP* - amount of seconds to sleep for before trying again. Defaults to a random number between 30 and 90.
|
300
|
+
* *RS_VSPHERE_CONNECT_TIMEOUT* - amount of seconds before retrying to connect to the VSphere API. Defaults to 60.
|
301
|
+
* *RS_VSPHERE_CONNECT_TRIES* - amount of attempts to connect to the VSphere API. Defaults to 10.
|
294
302
|
|
295
|
-
|
303
|
+
Set these variables, and run the usual rake command specifying the provider:
|
304
|
+
|
305
|
+
RS_PROVIDER='vsphere' bundle exec rake spec:system
|
296
306
|
|
297
|
-
In Jenkins, set the authentication variables above using environment variable injection. I recommend using the private environment variables feature for user & pass however so these do not get displayed in the console output. As with the vagrant provider however, turn
|
307
|
+
In Jenkins, set the authentication variables above using environment variable injection. I recommend using the private environment variables feature for user & pass however so these do not get displayed in the console output. As with the vagrant provider however, turn RS\_SET into a test matrix, containing all the sets you want to test against.
|
298
308
|
|
299
309
|
### Plugins to rspec-system
|
300
310
|
|
@@ -311,15 +321,20 @@ Libraries that provide test helpers, and setup helpers for testing development o
|
|
311
321
|
|
312
322
|
A node provider should provide the ability to launch nodes (or if they are already launched provide information to get to them), run commands on nodes, transfer files and shutdown nodes. That is, abstractions around other virtualisation, cloud or system tools.
|
313
323
|
|
314
|
-
Right now the
|
324
|
+
Right now the options are:
|
325
|
+
|
326
|
+
* vagrant\_virtualbox
|
327
|
+
* vagrant\_vmware\_fusion
|
328
|
+
* vsphere
|
329
|
+
|
330
|
+
... and these are installed with core. In the future we probably want to split these out to plugins, but the plugin system isn't quite ready for that yet.
|
315
331
|
|
316
332
|
#### The Future of Plugins
|
317
333
|
|
318
334
|
I want to start an eco-system of plugins for rspec-system, but do it in a sane way. Right now I see the following potential plugin types, if you think you can help please do:
|
319
335
|
|
320
336
|
* node providers - that is, abstractions around other virtualisation, cloud or system tools. Right now a NodeSet is tied to a virtual type, but I think this isn't granual enough. Some ideas for future providers are:
|
321
|
-
*
|
322
|
-
* vmware fusion - for using vmware fusion with vagrant
|
337
|
+
* other vagrant plugins - it should be reasonably easy to extend support out to new vagrant plugins, since most of the example plugins are already using a simple pattern to do this.
|
323
338
|
* razor - for launching bare metail nodes for testing purposes. Could be really useful to have baremetal tests for software that needs it like `facter`.
|
324
339
|
* manual - not everything has to be 'launched' I can see a need for defining a static configuration for older machines that can't be poked and peeked. Of course, we might need to add cleanup tasks for this case.
|
325
340
|
* helper libraries - libraries that provide test helpers, and setup helpers for testing development on the software in question.
|
@@ -335,9 +350,9 @@ These could be shipped as external gems, and plugged in to the rspec-system fram
|
|
335
350
|
|
336
351
|
So currently I've only integrated this with Jenkins. If you have luck doing it on other CI platforms, feel free to add to this documentation.
|
337
352
|
|
338
|
-
#### Jenkins
|
353
|
+
#### Jenkins
|
339
354
|
|
340
|
-
|
355
|
+
For virtualbox the setup tested with was:
|
341
356
|
|
342
357
|
* Single box - 32GB of RAM and 8 cpus
|
343
358
|
* Debian 7
|
@@ -346,28 +361,7 @@ My setup was:
|
|
346
361
|
* VirtualBox 4.2.10 (installed via packages from virtualbox)
|
347
362
|
* RVM with Ruby 2.0.0
|
348
363
|
|
349
|
-
|
350
|
-
|
351
|
-
* Setup your slave box to only have 1 executor (there is some bug here, something to do with vagrant not liking multiple projects)
|
352
|
-
* Create new matrix build
|
353
|
-
* Specify VCS settings etc. as per normal
|
354
|
-
* Create a user defined axis called 'RSPEC_SET' and add your nodesets in there: fedora-18-x64, centos-64-x64 etc.
|
355
|
-
* Use touchstone with a filter of RSPEC_SET=='centos-64-x64' so you don't chew up cycles running a whole batch of broken builds
|
356
|
-
* Create an execute shell job like so:
|
357
|
-
|
358
|
-
#!/bin/bash
|
359
|
-
set +e
|
360
|
-
|
361
|
-
[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm"
|
362
|
-
rvm use ruby-2.0.0
|
363
|
-
bundle install --path vendor/bundle
|
364
|
-
bundle exec rake spec:system
|
365
|
-
|
366
|
-
I went quite complex and had Github pull request integration working with this, and quite a few other nice features. If you need help setting it up get in touch.
|
367
|
-
|
368
|
-
#### Jenkins and the VSphere provider
|
369
|
-
|
370
|
-
My setup was:
|
364
|
+
Or for VSphere:
|
371
365
|
|
372
366
|
* Debian 7
|
373
367
|
* Jenkins 1.510
|
@@ -377,16 +371,17 @@ The setup for a job is basically:
|
|
377
371
|
|
378
372
|
* Create new matrix build
|
379
373
|
* Specify VCS settings etc. as per normal
|
380
|
-
* Create a user defined axis called '
|
381
|
-
* Use
|
382
|
-
*
|
374
|
+
* Create a user defined axis called 'RS\_SET' and add your nodesets in there: fedora-18-x64, centos-64-x64 etc.
|
375
|
+
* Use touchstone with a filter of RS\_SET=='centos-64-x64' so you don't chew up cycles running a whole batch of broken builds
|
376
|
+
* For the provider in question, make sure you have provided any custom configuration. For example VSphere requires a bunch of RS\_VSPHERE\_\* variables to be set. Make sure these are set using the environment variable injection facility.
|
383
377
|
* Create an execute shell job like so:
|
384
378
|
|
385
379
|
#!/bin/bash
|
386
380
|
set +e
|
381
|
+
|
387
382
|
[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm"
|
388
383
|
rvm use ruby-2.0.0
|
389
384
|
bundle install --path vendor/bundle
|
390
385
|
bundle exec rake spec:system
|
391
386
|
|
392
|
-
|
387
|
+
I went quite complex and had Github pull request integration working with this, and quite a few other nice features. If you need help setting it up get in touch.
|
data/lib/rspec-system.rb
CHANGED
data/lib/rspec-system/helper.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'rspec-system'
|
2
2
|
require 'rspec-system/result'
|
3
|
-
require 'rspec-system/internal_helpers'
|
4
3
|
require 'timeout'
|
5
4
|
|
6
5
|
module RSpecSystem
|
@@ -16,8 +15,6 @@ module RSpecSystem
|
|
16
15
|
#
|
17
16
|
# @abstract Subclass and override methods to create a helper object
|
18
17
|
class Helper
|
19
|
-
include RSpecSystem::InternalHelpers
|
20
|
-
|
21
18
|
# Cache of previous result data
|
22
19
|
# @api private
|
23
20
|
attr_reader :rd
|
@@ -169,7 +166,7 @@ module RSpecSystem
|
|
169
166
|
|
170
167
|
# Return default node
|
171
168
|
def default_node
|
172
|
-
|
169
|
+
RSpecSystem::NodeSet.create.default_node
|
173
170
|
end
|
174
171
|
|
175
172
|
# Returns a node by its name.
|
@@ -179,7 +176,7 @@ module RSpecSystem
|
|
179
176
|
# @param name [String] name of the node
|
180
177
|
# @return [RSpecSystem::Node] node found
|
181
178
|
def get_node_by_name(name)
|
182
|
-
|
179
|
+
RSpecSystem::NodeSet.create.nodes[name]
|
183
180
|
end
|
184
181
|
end
|
185
182
|
end
|
data/lib/rspec-system/helpers.rb
CHANGED
@@ -164,7 +164,7 @@ module RSpecSystem::Helpers
|
|
164
164
|
# @option options [String] :name the canonical name of the node
|
165
165
|
# @return [RSpecSystem::Node] node object
|
166
166
|
def node(options = {})
|
167
|
-
ns =
|
167
|
+
ns = RSpecSystem::NodeSet.create
|
168
168
|
options = {
|
169
169
|
:name => ns.default_node.name,
|
170
170
|
}.merge(options)
|
@@ -7,7 +7,7 @@ module RSpecSystem::Helpers
|
|
7
7
|
properties :success
|
8
8
|
|
9
9
|
def initialize(opts, clr, &block)
|
10
|
-
ns =
|
10
|
+
ns = RSpecSystem::NodeSet.create
|
11
11
|
opts = {
|
12
12
|
:source_path => opts[:sp],
|
13
13
|
:destination_path => opts[:dp],
|
@@ -32,10 +32,7 @@ module RSpecSystem::Helpers
|
|
32
32
|
|
33
33
|
# Gathers new results by executing the resource action
|
34
34
|
def execute
|
35
|
-
ns =
|
36
|
-
d = opts[:d]
|
37
|
-
sp = opts[:sp]
|
38
|
-
dp = opts[:dp]
|
35
|
+
ns = RSpecSystem::NodeSet.create
|
39
36
|
|
40
37
|
result = ns.rcp(opts)
|
41
38
|
{ :success => result }
|
data/lib/rspec-system/node.rb
CHANGED
@@ -3,8 +3,6 @@ require 'rspec-system'
|
|
3
3
|
module RSpecSystem
|
4
4
|
# This class represents a node in a nodeset
|
5
5
|
class Node
|
6
|
-
include RSpecSystem::InternalHelpers
|
7
|
-
|
8
6
|
# Static helper for generating a node direct from the hash returned by
|
9
7
|
# the nodeset YAML file.
|
10
8
|
#
|
@@ -44,7 +42,7 @@ module RSpecSystem
|
|
44
42
|
# TODO: do not support not prefabs yet
|
45
43
|
raise "No prefab defined, bailing"
|
46
44
|
else
|
47
|
-
@prefab = RSpecSystem::Prefab.prefab(prefab, custom_prefabs_path)
|
45
|
+
@prefab = RSpecSystem::Prefab.prefab(prefab, @custom_prefabs_path)
|
48
46
|
@facts = @prefab.facts
|
49
47
|
@provider_specifics = @prefab.provider_specifics
|
50
48
|
end
|
@@ -5,13 +5,21 @@ module RSpecSystem
|
|
5
5
|
#
|
6
6
|
# @return [RSpecSystem::NodeSet::Base] returns an object based on the Base
|
7
7
|
# abstract class.
|
8
|
-
|
8
|
+
# @api private
|
9
|
+
def self.create
|
10
|
+
provider = RSpec.configuration.rs_provider
|
11
|
+
custom_prefabs = RSpec.configuration.rs_custom_prefabs
|
12
|
+
setname = RSpec.configuration.rs_set || RSpec.configuration.rs_config['default_set']
|
13
|
+
options = {:destroy => RSpec.configuration.rs_destroy}
|
14
|
+
config = RSpec.configuration.rs_config['sets'][setname]
|
15
|
+
|
9
16
|
begin
|
10
|
-
require "rspec-system/node_set/#{
|
17
|
+
require "rspec-system/node_set/#{provider.downcase}"
|
11
18
|
rescue LoadError => e
|
12
|
-
raise "Unsupported
|
19
|
+
raise "Unsupported provider #{provider}: #{e}"
|
13
20
|
end
|
14
|
-
|
21
|
+
class_name = provider.split("_").map {|v| v.capitalize }.join
|
22
|
+
const_get(class_name).new(setname, config, custom_prefabs, options)
|
15
23
|
end
|
16
24
|
end
|
17
25
|
end
|
@@ -30,9 +30,83 @@ module RSpecSystem
|
|
30
30
|
# Setup the NodeSet by starting all nodes.
|
31
31
|
#
|
32
32
|
# @return [void]
|
33
|
-
# @abstract Override this method and provide your own node launching code
|
34
33
|
def setup
|
35
|
-
|
34
|
+
launch
|
35
|
+
connect
|
36
|
+
configure
|
37
|
+
end
|
38
|
+
|
39
|
+
# Launch nodes
|
40
|
+
#
|
41
|
+
# @return [void]
|
42
|
+
# @abstract Override this method and provide your own launch code
|
43
|
+
def launch
|
44
|
+
raise RuntimeError "Unimplemented method #launch"
|
45
|
+
end
|
46
|
+
|
47
|
+
# Connect nodes
|
48
|
+
#
|
49
|
+
# @return [void]
|
50
|
+
# @abstract Override this method and provide your own connect code
|
51
|
+
def connect
|
52
|
+
raise RuntimeError "Unimplemented method #connect"
|
53
|
+
end
|
54
|
+
|
55
|
+
# Configure nodes
|
56
|
+
#
|
57
|
+
# This is the global configure method that sets up a node before tests are
|
58
|
+
# run, making sure any important preparation steps are executed.
|
59
|
+
#
|
60
|
+
# * fixup profile to stop using mesg to avoid extraneous noise
|
61
|
+
# * ntp synchronisation
|
62
|
+
# * hostname & hosts setup
|
63
|
+
#
|
64
|
+
# @return [void]
|
65
|
+
# @abstract Override this method and provide your own configure code
|
66
|
+
def configure
|
67
|
+
nodes.each do |k,v|
|
68
|
+
rs_storage = RSpec.configuration.rs_storage[:nodes][k]
|
69
|
+
|
70
|
+
# Fixup profile to avoid noise
|
71
|
+
if v.facts['osfamily'] == 'Debian'
|
72
|
+
shell(:n => k, :c => "sed -i 's/^mesg n/# mesg n/' /root/.profile")
|
73
|
+
end
|
74
|
+
|
75
|
+
# Setup ntp
|
76
|
+
if v.facts['osfamily'] == 'Debian' then
|
77
|
+
shell(:n => k, :c => 'apt-get install -y ntpdate')
|
78
|
+
elsif v.facts['osfamily'] == 'RedHat' then
|
79
|
+
if v.facts['lsbmajdistrelease'] == '5' then
|
80
|
+
shell(:n => k, :c => 'yum install -y ntp')
|
81
|
+
else
|
82
|
+
shell(:n => k, :c => 'yum install -y ntpdate')
|
83
|
+
end
|
84
|
+
end
|
85
|
+
shell(:n => k, :c => 'ntpdate -u pool.ntp.org')
|
86
|
+
|
87
|
+
# Grab IP address for host, if we don't already have one
|
88
|
+
rs_storage[:ipaddress] ||= shell(:n => k, :c => "ip a|awk '/g/{print$2}' | cut -d/ -f1 | head -1").stdout.chomp
|
89
|
+
|
90
|
+
# Configure local hostname and hosts file
|
91
|
+
shell(:n => k, :c => "hostname #{k}")
|
92
|
+
|
93
|
+
if v.facts['osfamily'] == 'Debian' then
|
94
|
+
shell(:n => k, :c => "echo '#{k}' > /etc/hostname")
|
95
|
+
end
|
96
|
+
|
97
|
+
hosts = <<-EOS
|
98
|
+
#{rs_storage[:ipaddress]} #{k}
|
99
|
+
127.0.0.1 #{k} localhost
|
100
|
+
::1 #{k} localhost
|
101
|
+
EOS
|
102
|
+
shell(:n => k, :c => "echo '#{hosts}' > /etc/hosts")
|
103
|
+
|
104
|
+
# Display setup for diagnostics
|
105
|
+
shell(:n => k, :c => 'cat /etc/hosts')
|
106
|
+
shell(:n => k, :c => 'hostname')
|
107
|
+
shell(:n => k, :c => 'hostname -f')
|
108
|
+
end
|
109
|
+
nil
|
36
110
|
end
|
37
111
|
|
38
112
|
# Shutdown the NodeSet by shutting down or pausing all nodes.
|
@@ -40,7 +114,7 @@ module RSpecSystem
|
|
40
114
|
# @return [void]
|
41
115
|
# @abstract Override this method and provide your own node teardown code
|
42
116
|
def teardown
|
43
|
-
raise "Unimplemented method #teardown"
|
117
|
+
raise RuntimeError "Unimplemented method #teardown"
|
44
118
|
end
|
45
119
|
|
46
120
|
# Run a command on a host in the NodeSet.
|
@@ -49,7 +123,11 @@ module RSpecSystem
|
|
49
123
|
# @return [Hash] a hash containing :stderr, :stdout and :exit_code
|
50
124
|
# @abstract Override this method providing your own shell running code
|
51
125
|
def run(opts)
|
52
|
-
|
126
|
+
dest = opts[:n].name
|
127
|
+
cmd = opts[:c]
|
128
|
+
|
129
|
+
ssh = RSpec.configuration.rs_storage[:nodes][dest][:ssh]
|
130
|
+
ssh_exec!(ssh, cmd)
|
53
131
|
end
|
54
132
|
|
55
133
|
# Copy a file to the host in the NodeSet.
|
@@ -61,14 +139,28 @@ module RSpecSystem
|
|
61
139
|
# @return [Boolean] returns true if command succeeded, false otherwise
|
62
140
|
# @abstract Override this method providing your own file transfer code
|
63
141
|
def rcp(opts)
|
64
|
-
|
142
|
+
dest = opts[:d].name
|
143
|
+
source = opts[:sp]
|
144
|
+
dest_path = opts[:dp]
|
145
|
+
|
146
|
+
# Do the copy and print out results for debugging
|
147
|
+
ssh = RSpec.configuration.rs_storage[:nodes][dest][:ssh]
|
148
|
+
|
149
|
+
begin
|
150
|
+
ssh.scp.upload! source.to_s, dest_path.to_s, :recursive => true
|
151
|
+
rescue => e
|
152
|
+
log.error("Error with scp of file #{source} to #{dest}:#{dest_path}")
|
153
|
+
raise e
|
154
|
+
end
|
155
|
+
|
156
|
+
true
|
65
157
|
end
|
66
158
|
|
67
159
|
# @!group Common Methods
|
68
160
|
|
69
161
|
# Return environment type
|
70
|
-
def
|
71
|
-
self.class::
|
162
|
+
def provider_type
|
163
|
+
self.class::PROVIDER_TYPE
|
72
164
|
end
|
73
165
|
|
74
166
|
# Return default node
|
@@ -105,6 +197,39 @@ module RSpecSystem
|
|
105
197
|
'/tmp/' + random_string
|
106
198
|
end
|
107
199
|
|
200
|
+
# Connect via SSH in a resilient way
|
201
|
+
#
|
202
|
+
# @param [Hash] opts
|
203
|
+
# @option opts [String] :host Host to connect to
|
204
|
+
# @option opts [String] :user User to connect as
|
205
|
+
# @option opts [Hash] :net_ssh_options Options hash as used by `Net::SSH.start`
|
206
|
+
# @return [Net::SSH::Connection::Session]
|
207
|
+
# @api protected
|
208
|
+
def ssh_connect(opts = {})
|
209
|
+
ssh_sleep = RSpec.configuration.rs_ssh_sleep
|
210
|
+
ssh_tries = RSpec.configuration.rs_ssh_tries
|
211
|
+
ssh_timeout = RSpec.configuration.rs_ssh_timeout
|
212
|
+
|
213
|
+
tries = 0
|
214
|
+
begin
|
215
|
+
timeout(ssh_timeout) do
|
216
|
+
output << bold(color("localhost$", :green)) << " ssh -l #{opts[:user]} #{opts[:host]}\n"
|
217
|
+
Net::SSH.start(opts[:host], opts[:user], opts[:net_ssh_options])
|
218
|
+
end
|
219
|
+
rescue Timeout::Error, SystemCallError => e
|
220
|
+
tries += 1
|
221
|
+
output << e.message << "\n"
|
222
|
+
if tries < ssh_tries
|
223
|
+
log.info("Sleeping for #{ssh_sleep} seconds then trying again ...")
|
224
|
+
sleep ssh_sleep
|
225
|
+
retry
|
226
|
+
else
|
227
|
+
log.error("Inability to connect to host, already tried #{tries} times, throwing exception")
|
228
|
+
raise e
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
108
233
|
# Execute command via SSH.
|
109
234
|
#
|
110
235
|
# A special version of exec! from Net::SSH that returns exit code and exit
|