beaker 2.18.0 → 2.19.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 +8 -8
- data/HISTORY.md +699 -2
- data/acceptance/lib/beaker/acceptance/install_utils.rb +58 -0
- data/acceptance/pre_suite/puppet_gem/install.rb +1 -8
- data/acceptance/pre_suite/puppet_git/install.rb +6 -65
- data/acceptance/pre_suite/puppet_pkg/install.rb +1 -1
- data/acceptance/tests/foss_utils/clone_git_repo_on.rb +49 -0
- data/beaker.gemspec +2 -0
- data/lib/beaker/command.rb +1 -1
- data/lib/beaker/dsl/helpers/puppet_helpers.rb +8 -6
- data/lib/beaker/dsl/helpers/web_helpers.rb +2 -1
- data/lib/beaker/dsl/install_utils/aio_defaults.rb +0 -3
- data/lib/beaker/dsl/install_utils/foss_defaults.rb +19 -0
- data/lib/beaker/dsl/install_utils/foss_utils.rb +164 -67
- data/lib/beaker/dsl/install_utils/pe_defaults.rb +9 -11
- data/lib/beaker/dsl/install_utils/pe_utils.rb +48 -64
- data/lib/beaker/dsl/install_utils/puppet_utils.rb +43 -0
- data/lib/beaker/dsl/install_utils/windows_utils.rb +144 -0
- data/lib/beaker/dsl/roles.rb +20 -3
- data/lib/beaker/dsl/structure.rb +14 -3
- data/lib/beaker/host/freebsd/pkg.rb +18 -0
- data/lib/beaker/host/freebsd.rb +2 -0
- data/lib/beaker/host/unix/exec.rb +3 -3
- data/lib/beaker/host/unix/pkg.rb +37 -0
- data/lib/beaker/host/windows/exec.rb +3 -0
- data/lib/beaker/host.rb +38 -9
- data/lib/beaker/host_prebuilt_steps.rb +21 -11
- data/lib/beaker/hypervisor/aws_sdk.rb +22 -18
- data/lib/beaker/hypervisor/docker.rb +7 -0
- data/lib/beaker/hypervisor/openstack.rb +1 -0
- data/lib/beaker/hypervisor/vagrant_virtualbox.rb +10 -5
- data/lib/beaker/hypervisor/vmpooler.rb +4 -0
- data/lib/beaker/logger.rb +12 -1
- data/lib/beaker/options/command_line_parser.rb +9 -0
- data/lib/beaker/options/options_hash.rb +3 -296
- data/lib/beaker/options/parser.rb +12 -0
- data/lib/beaker/options/presets.rb +0 -1
- data/lib/beaker/platform.rb +3 -1
- data/lib/beaker/ssh_connection.rb +48 -23
- data/lib/beaker/test_case.rb +1 -1
- data/lib/beaker/version.rb +1 -1
- data/spec/beaker/dsl/helpers/puppet_helpers_spec.rb +0 -1
- data/spec/beaker/dsl/helpers/web_helpers_spec.rb +10 -1
- data/spec/beaker/dsl/install_utils/foss_utils_spec.rb +247 -49
- data/spec/beaker/dsl/install_utils/pe_utils_spec.rb +116 -26
- data/spec/beaker/dsl/install_utils/puppet_utils_spec.rb +57 -0
- data/spec/beaker/dsl/install_utils/windows_utils_spec.rb +132 -0
- data/spec/beaker/dsl/roles_spec.rb +36 -5
- data/spec/beaker/dsl/structure_spec.rb +9 -2
- data/spec/beaker/host/unix/pkg_spec.rb +26 -6
- data/spec/beaker/host_prebuilt_steps_spec.rb +3 -2
- data/spec/beaker/host_spec.rb +24 -6
- data/spec/beaker/hypervisor/aixer_spec.rb +1 -1
- data/spec/beaker/hypervisor/aws_sdk_spec.rb +595 -58
- data/spec/beaker/hypervisor/docker_spec.rb +2 -1
- data/spec/beaker/hypervisor/solaris_spec.rb +1 -0
- data/spec/beaker/hypervisor/vagrant_spec.rb +20 -5
- data/spec/beaker/hypervisor/vagrant_virtualbox_spec.rb +1 -1
- data/spec/beaker/logger_spec.rb +39 -0
- data/spec/beaker/options/command_line_parser_spec.rb +2 -2
- data/spec/beaker/options/options_hash_spec.rb +1 -102
- data/spec/beaker/options/parser_spec.rb +19 -0
- data/spec/beaker/options/pe_version_scaper_spec.rb +11 -1
- data/spec/beaker/options/presets_spec.rb +8 -0
- data/spec/beaker/ssh_connection_spec.rb +39 -21
- data/spec/helpers.rb +9 -3
- data/spec/mocks.rb +2 -0
- metadata +35 -11
- data/lib/beaker/answers/version20.rb +0 -120
- data/lib/beaker/answers/version28.rb +0 -121
- data/lib/beaker/answers/version30.rb +0 -227
- data/lib/beaker/answers/version32.rb +0 -44
- data/lib/beaker/answers/version34.rb +0 -51
- data/lib/beaker/answers/version38.rb +0 -29
- data/lib/beaker/answers/version40.rb +0 -44
- data/lib/beaker/answers.rb +0 -143
- data/spec/beaker/answers_spec.rb +0 -547
|
@@ -1,44 +1,11 @@
|
|
|
1
|
+
require 'stringify-hash'
|
|
2
|
+
|
|
1
3
|
module Beaker
|
|
2
4
|
module Options
|
|
3
5
|
|
|
4
6
|
# A hash that treats Symbol and String keys interchangeably
|
|
5
7
|
# and recursively merges hashes
|
|
6
|
-
class OptionsHash <
|
|
7
|
-
|
|
8
|
-
# The dividor between elements when OptionsHash is dumped
|
|
9
|
-
DIV = ' '
|
|
10
|
-
|
|
11
|
-
# The end of line when dumping
|
|
12
|
-
EOL = "\n"
|
|
13
|
-
|
|
14
|
-
# Get value for given key, search for both k as String and k as Symbol,
|
|
15
|
-
# if not present return nil
|
|
16
|
-
#
|
|
17
|
-
# @param [Object] k The key to find, searches for both k as String
|
|
18
|
-
# and k as Symbol
|
|
19
|
-
#
|
|
20
|
-
# @example Use this method to return the value for a given key
|
|
21
|
-
# a['key'] = 'value'
|
|
22
|
-
# a['key'] == a[:key] == 'value'
|
|
23
|
-
#
|
|
24
|
-
# @return [nil, Object] Return the Object found at given key,
|
|
25
|
-
# or nil if no Object found
|
|
26
|
-
def [] k
|
|
27
|
-
super(k.to_s) || super(k.to_sym)
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
# Set Symbol key to Object value
|
|
31
|
-
# @param [Object] k The key to associated with the value,
|
|
32
|
-
# converted to Symbol key
|
|
33
|
-
# @param [Object] v The value to store in the ObjectHash
|
|
34
|
-
#
|
|
35
|
-
# @example Use this method to set the value for a key
|
|
36
|
-
# a['key'] = 'value'
|
|
37
|
-
#
|
|
38
|
-
# @return [Object] Return the Object value just stored
|
|
39
|
-
def []=k,v
|
|
40
|
-
super(k.to_sym, v)
|
|
41
|
-
end
|
|
8
|
+
class OptionsHash < StringifyHash
|
|
42
9
|
|
|
43
10
|
# Determine if type of ObjectHash is pe, defaults to true
|
|
44
11
|
#
|
|
@@ -66,271 +33,11 @@ module Beaker
|
|
|
66
33
|
:pe
|
|
67
34
|
when /foss/
|
|
68
35
|
:foss
|
|
69
|
-
when /aio/
|
|
70
|
-
:aio
|
|
71
36
|
else
|
|
72
37
|
:foss
|
|
73
38
|
end
|
|
74
39
|
end
|
|
75
40
|
|
|
76
|
-
# Determine if key is stored in ObjectHash
|
|
77
|
-
# @param [Object] k The key to find in ObjectHash, searches for
|
|
78
|
-
# both k as String and k as Symbol
|
|
79
|
-
#
|
|
80
|
-
# @example Use this method to set the value for a key
|
|
81
|
-
# a['key'] = 'value'
|
|
82
|
-
# a.has_key[:key] == true
|
|
83
|
-
#
|
|
84
|
-
# @return [Boolean]
|
|
85
|
-
def has_key? k
|
|
86
|
-
super(k.to_s) || super(k.to_sym)
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
# Determine key=>value entry in OptionsHash, remove both value at
|
|
90
|
-
# String key and value at Symbol key
|
|
91
|
-
#
|
|
92
|
-
# @param [Object] k The key to delete in ObjectHash,
|
|
93
|
-
# deletes both k as String and k as Symbol
|
|
94
|
-
#
|
|
95
|
-
# @example Use this method to set the value for a key
|
|
96
|
-
# a['key'] = 'value'
|
|
97
|
-
# a.delete[:key] == 'value'
|
|
98
|
-
#
|
|
99
|
-
# @return [Object, nil] The Object deleted at value,
|
|
100
|
-
# nil if no Object deleted
|
|
101
|
-
def delete k
|
|
102
|
-
super(k.to_s) || super(k.to_sym)
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
# Recursively merge and OptionsHash with an OptionsHash or Hash
|
|
106
|
-
#
|
|
107
|
-
# @param [OptionsHash] base The hash to merge into
|
|
108
|
-
# @param [OptionsHash, Hash] hash The hash to merge from
|
|
109
|
-
#
|
|
110
|
-
# @example
|
|
111
|
-
# base = { :key => { :subkey1 => 'subval', :subkey2 => 'subval' } }
|
|
112
|
-
# hash = { :key => { :subkey1 => 'newval'} }
|
|
113
|
-
#
|
|
114
|
-
# rmerge(base, hash)
|
|
115
|
-
# #=> {:key =>
|
|
116
|
-
# {:subkey1 => 'newval',
|
|
117
|
-
# :subkey2 => 'subval'}}
|
|
118
|
-
#
|
|
119
|
-
# @return [OptionsHash] The combined bash and hash
|
|
120
|
-
def rmerge base, hash
|
|
121
|
-
return base unless hash.is_a?(Hash) || hash.is_a?(OptionsHash)
|
|
122
|
-
hash.each do |key, v|
|
|
123
|
-
if (base[key].is_a?(Hash) || base[key].is_a?(OptionsHash)) && (hash[key].is_a?(Hash) || hash[key].is_a?(OptionsHash))
|
|
124
|
-
rmerge(base[key], hash[key])
|
|
125
|
-
elsif hash[key].is_a?(Hash)
|
|
126
|
-
base[key] = OptionsHash.new.merge(hash[key])
|
|
127
|
-
else
|
|
128
|
-
base[key]= hash[key]
|
|
129
|
-
end
|
|
130
|
-
end
|
|
131
|
-
base
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
# Create new OptionsHash from recursively merged self with an OptionsHash or Hash
|
|
135
|
-
#
|
|
136
|
-
# @param [OptionsHash, Hash] hash The hash to merge from
|
|
137
|
-
#
|
|
138
|
-
# @example
|
|
139
|
-
# base = { :key => { :subkey1 => 'subval', :subkey2 => 'subval' } }
|
|
140
|
-
# hash = { :key => { :subkey1 => 'newval'} }
|
|
141
|
-
#
|
|
142
|
-
# base.merge(hash)
|
|
143
|
-
# #=> {:key =>
|
|
144
|
-
# {:subkey1 => 'newval',
|
|
145
|
-
# :subkey2 => 'subval' }
|
|
146
|
-
#
|
|
147
|
-
# @return [OptionsHash] The combined hash
|
|
148
|
-
def merge hash
|
|
149
|
-
#make a deep copy into an empty hash object
|
|
150
|
-
merged_hash = rmerge(OptionsHash.new, self)
|
|
151
|
-
rmerge(merged_hash, hash)
|
|
152
|
-
end
|
|
153
|
-
|
|
154
|
-
# Recursively merge self with an OptionsHash or Hash
|
|
155
|
-
#
|
|
156
|
-
# @param [OptionsHash, Hash] hash The hash to merge from
|
|
157
|
-
#
|
|
158
|
-
# @example
|
|
159
|
-
# base = { :key => { :subkey1 => 'subval', :subkey2 => 'subval' } }
|
|
160
|
-
# hash = { :key => { :subkey1 => 'newval'} }
|
|
161
|
-
#
|
|
162
|
-
# base.merge!(hash)
|
|
163
|
-
# #=> {:key =>
|
|
164
|
-
# {:subkey1 => 'newval',
|
|
165
|
-
# :subkey2 => 'subval' }
|
|
166
|
-
#
|
|
167
|
-
# @return [OptionsHash] The combined hash
|
|
168
|
-
def merge! hash
|
|
169
|
-
rmerge(self, hash)
|
|
170
|
-
end
|
|
171
|
-
|
|
172
|
-
# Helper for formatting collections
|
|
173
|
-
# Computes the indentation level for elements of the collection
|
|
174
|
-
# Yields indentation to block to so the caller can create
|
|
175
|
-
# map of element strings
|
|
176
|
-
# Places delimiters in the correct location
|
|
177
|
-
# Joins everything with correct EOL
|
|
178
|
-
#
|
|
179
|
-
#
|
|
180
|
-
# !@visibility private
|
|
181
|
-
def as_coll( opening, closing, in_lvl, in_inc, &block )
|
|
182
|
-
delim_indent = in_inc * in_lvl
|
|
183
|
-
elem_indent = in_inc * (in_lvl + 1)
|
|
184
|
-
|
|
185
|
-
open_brace = opening
|
|
186
|
-
close_brace = delim_indent + closing
|
|
187
|
-
|
|
188
|
-
fmtd_coll = block.call( elem_indent )
|
|
189
|
-
str_coll = fmtd_coll.join( ',' + EOL )
|
|
190
|
-
|
|
191
|
-
return open_brace + EOL + str_coll + EOL + close_brace
|
|
192
|
-
end
|
|
193
|
-
|
|
194
|
-
# Pretty prints a collection
|
|
195
|
-
#
|
|
196
|
-
# @param [Enumerable] collection The collection to be printed
|
|
197
|
-
# @param [Integer] in_lvl The level of indentation
|
|
198
|
-
# @param [String] in_inc The increment to indent
|
|
199
|
-
#
|
|
200
|
-
# @example
|
|
201
|
-
# base = {:key => { :subkey1 => 'subval', :subkey2 => ['subval'] }}
|
|
202
|
-
# self.fmt_collection( base )
|
|
203
|
-
# #=> '{
|
|
204
|
-
# "key": {
|
|
205
|
-
# "subkey": "subval",
|
|
206
|
-
# "subkey2": [
|
|
207
|
-
# "subval"
|
|
208
|
-
# ]
|
|
209
|
-
# }
|
|
210
|
-
# }'
|
|
211
|
-
#
|
|
212
|
-
# @return [String] The collection as a pretty JSON object
|
|
213
|
-
def fmt_collection( collection, in_lvl = 0, in_inc = DIV )
|
|
214
|
-
if collection.respond_to? :each_pair
|
|
215
|
-
string = fmt_assoc( collection, in_lvl, in_inc )
|
|
216
|
-
else
|
|
217
|
-
string = fmt_list( collection, in_lvl, in_inc )
|
|
218
|
-
end
|
|
219
|
-
|
|
220
|
-
return string
|
|
221
|
-
end
|
|
222
|
-
|
|
223
|
-
# Pretty prints an associative collection
|
|
224
|
-
#
|
|
225
|
-
# @param [#each_pair] coll The collection to be printed
|
|
226
|
-
# @param [Integer] in_lvl The level of indentation
|
|
227
|
-
# @param [String] in_inc The increment to indent
|
|
228
|
-
#
|
|
229
|
-
# @example
|
|
230
|
-
# base = { :key => 'value', :key2 => 'value' }
|
|
231
|
-
# self.fmt_assoc( base )
|
|
232
|
-
# #=> '{
|
|
233
|
-
# "key": "value",
|
|
234
|
-
# "key2": "value"
|
|
235
|
-
# }'
|
|
236
|
-
#
|
|
237
|
-
# @return [String] The collection as a pretty JSON object
|
|
238
|
-
def fmt_assoc( coll, in_lvl = 0, in_inc = DIV )
|
|
239
|
-
if coll.empty?
|
|
240
|
-
return '{}'
|
|
241
|
-
else
|
|
242
|
-
as_coll '{', '}', in_lvl, in_inc do |elem_indent|
|
|
243
|
-
coll.map do |key, value|
|
|
244
|
-
assoc_line = elem_indent + '"' + key.to_s + '"' + ': '
|
|
245
|
-
assoc_line += fmt_value( value, in_lvl, in_inc )
|
|
246
|
-
end
|
|
247
|
-
end
|
|
248
|
-
end
|
|
249
|
-
end
|
|
250
|
-
|
|
251
|
-
# Pretty prints a list collection
|
|
252
|
-
#
|
|
253
|
-
# @param [#each] coll The collection to be printed
|
|
254
|
-
# @param [Integer] in_lvl The level of indentation
|
|
255
|
-
# @param [String] in_inc The increment to indent
|
|
256
|
-
#
|
|
257
|
-
# @example
|
|
258
|
-
# base = [ 'first', 'second' ]
|
|
259
|
-
# self.fmt_list( base )
|
|
260
|
-
# #=> '[
|
|
261
|
-
# "first",
|
|
262
|
-
# "second"
|
|
263
|
-
# ]'
|
|
264
|
-
#
|
|
265
|
-
# @return [String] The collection as a pretty JSON object
|
|
266
|
-
def fmt_list( coll, in_lvl = 0, in_inc = DIV )
|
|
267
|
-
if coll.empty?
|
|
268
|
-
return '[]'
|
|
269
|
-
else
|
|
270
|
-
as_coll '[', ']', in_lvl, in_inc do |indent|
|
|
271
|
-
coll.map do |el|
|
|
272
|
-
indent + fmt_value( el, in_lvl, in_inc )
|
|
273
|
-
end
|
|
274
|
-
end
|
|
275
|
-
end
|
|
276
|
-
end
|
|
277
|
-
|
|
278
|
-
# Chooses between collection and primitive formatting
|
|
279
|
-
#
|
|
280
|
-
# !@visibility private
|
|
281
|
-
def fmt_value( value, in_lvl = 0, in_inc = DIV )
|
|
282
|
-
if value.kind_of? Enumerable and not value.is_a? String
|
|
283
|
-
fmt_collection( value, in_lvl + 1, in_inc )
|
|
284
|
-
else
|
|
285
|
-
fmt_basic( value )
|
|
286
|
-
end
|
|
287
|
-
end
|
|
288
|
-
|
|
289
|
-
# Pretty prints primitive JSON values
|
|
290
|
-
#
|
|
291
|
-
# @param [Object] value The collection to be printed
|
|
292
|
-
#
|
|
293
|
-
# @example
|
|
294
|
-
# self.fmt_value( 4 )
|
|
295
|
-
# #=> '4'
|
|
296
|
-
#
|
|
297
|
-
# @example
|
|
298
|
-
# self.fmt_value( true )
|
|
299
|
-
# #=> 'true'
|
|
300
|
-
#
|
|
301
|
-
# @example
|
|
302
|
-
# self.fmt_value( nil )
|
|
303
|
-
# #=> 'null'
|
|
304
|
-
#
|
|
305
|
-
# @example
|
|
306
|
-
# self.fmt_value( 'string' )
|
|
307
|
-
# #=> '"string"'
|
|
308
|
-
#
|
|
309
|
-
# @return [String] The value as a valid JSON primitive
|
|
310
|
-
def fmt_basic( value )
|
|
311
|
-
case value
|
|
312
|
-
when Numeric, TrueClass, FalseClass then value.to_s
|
|
313
|
-
when NilClass then "null"
|
|
314
|
-
else "\"#{value}\""
|
|
315
|
-
end
|
|
316
|
-
end
|
|
317
|
-
|
|
318
|
-
# Pretty print the options as JSON
|
|
319
|
-
#
|
|
320
|
-
# @example
|
|
321
|
-
# base = { :key => { :subkey1 => 'subval', :subkey2 => 'subval' } }
|
|
322
|
-
# base.dump
|
|
323
|
-
# #=> '{
|
|
324
|
-
# "key": {
|
|
325
|
-
# "subkey1": "subval",
|
|
326
|
-
# "subkey2": 2
|
|
327
|
-
# }
|
|
328
|
-
# }
|
|
329
|
-
#
|
|
330
|
-
# @return [String] The description of self
|
|
331
|
-
def dump
|
|
332
|
-
fmt_collection( self, 0, DIV )
|
|
333
|
-
end
|
|
334
41
|
end
|
|
335
42
|
end
|
|
336
43
|
end
|
|
@@ -328,6 +328,7 @@ module Beaker
|
|
|
328
328
|
end
|
|
329
329
|
|
|
330
330
|
normalize_and_validate_tags()
|
|
331
|
+
resolve_symlinks()
|
|
331
332
|
|
|
332
333
|
#set the default role
|
|
333
334
|
set_default_host!(@options[:HOSTS])
|
|
@@ -365,6 +366,17 @@ module Beaker
|
|
|
365
366
|
end
|
|
366
367
|
end
|
|
367
368
|
|
|
369
|
+
# resolves all file symlinks that require it.
|
|
370
|
+
#
|
|
371
|
+
# @note doing it here allows us to not need duplicate logic, which we
|
|
372
|
+
# would need if we were doing it in the parser (--hosts & --config)
|
|
373
|
+
#
|
|
374
|
+
# @return nil
|
|
375
|
+
# @api public
|
|
376
|
+
def resolve_symlinks()
|
|
377
|
+
@options[:hosts_file] = File.realpath(@options[:hosts_file]) if @options[:hosts_file]
|
|
378
|
+
end
|
|
379
|
+
|
|
368
380
|
private
|
|
369
381
|
|
|
370
382
|
# @api private
|
data/lib/beaker/platform.rb
CHANGED
|
@@ -3,7 +3,7 @@ module Beaker
|
|
|
3
3
|
# all String methods while adding several platform-specific use cases.
|
|
4
4
|
class Platform < String
|
|
5
5
|
# Supported platforms
|
|
6
|
-
PLATFORMS = /^(cisco|
|
|
6
|
+
PLATFORMS = /^(cisco|(free|open)bsd|osx|centos|fedora|debian|oracle|redhat|scientific|sles|ubuntu|windows|solaris|aix|el|eos|cumulus|f5)\-.+\-.+$/
|
|
7
7
|
|
|
8
8
|
# Platform version numbers vs. codenames conversion hash
|
|
9
9
|
PLATFORM_VERSION_CODES =
|
|
@@ -44,6 +44,8 @@ module Beaker
|
|
|
44
44
|
# Creates the Platform object. Checks to ensure that the platform String
|
|
45
45
|
# provided meets the platform formatting rules. Platforms name must be of
|
|
46
46
|
# the format /^OSFAMILY-VERSION-ARCH.*$/ where OSFAMILY is one of:
|
|
47
|
+
# * freebsd
|
|
48
|
+
# * openbsd
|
|
47
49
|
# * osx
|
|
48
50
|
# * centos
|
|
49
51
|
# * fedora
|
|
@@ -6,6 +6,7 @@ module Beaker
|
|
|
6
6
|
class SshConnection
|
|
7
7
|
|
|
8
8
|
attr_accessor :logger
|
|
9
|
+
attr_accessor :ip, :vmhostname, :hostname
|
|
9
10
|
|
|
10
11
|
RETRYABLE_EXCEPTIONS = [
|
|
11
12
|
SocketError,
|
|
@@ -21,41 +22,65 @@ module Beaker
|
|
|
21
22
|
IOError,
|
|
22
23
|
]
|
|
23
24
|
|
|
24
|
-
def initialize
|
|
25
|
-
@
|
|
25
|
+
def initialize name_hash, user = nil, ssh_opts = {}, options = {}
|
|
26
|
+
@vmhostname = name_hash[:vmhostname]
|
|
27
|
+
@ip = name_hash[:ip]
|
|
28
|
+
@hostname = name_hash[:hostname]
|
|
26
29
|
@user = user
|
|
27
30
|
@ssh_opts = ssh_opts
|
|
28
31
|
@logger = options[:logger]
|
|
29
32
|
@options = options
|
|
30
33
|
end
|
|
31
34
|
|
|
32
|
-
def self.connect
|
|
33
|
-
connection = new
|
|
35
|
+
def self.connect name_hash, user = 'root', ssh_opts = {}, options = {}
|
|
36
|
+
connection = new name_hash, user, ssh_opts, options
|
|
34
37
|
connection.connect
|
|
35
38
|
connection
|
|
36
39
|
end
|
|
37
40
|
|
|
41
|
+
def connect_block host, user, ssh_opts
|
|
42
|
+
try = 1
|
|
43
|
+
last_wait = 2
|
|
44
|
+
wait = 3
|
|
45
|
+
begin
|
|
46
|
+
@logger.debug "Attempting ssh connection to #{host}, user: #{user}, opts: #{ssh_opts}"
|
|
47
|
+
Net::SSH.start(host, user, ssh_opts)
|
|
48
|
+
rescue *RETRYABLE_EXCEPTIONS => e
|
|
49
|
+
if try <= 8
|
|
50
|
+
@logger.warn "Try #{try} -- Host #{host} unreachable: #{e.class.name} - #{e.message}"
|
|
51
|
+
@logger.warn "Trying again in #{wait} seconds"
|
|
52
|
+
sleep wait
|
|
53
|
+
(last_wait, wait) = wait, last_wait + wait
|
|
54
|
+
try += 1
|
|
55
|
+
retry
|
|
56
|
+
else
|
|
57
|
+
@logger.warn "Failed to connect to #{host}, after #{try} attempts"
|
|
58
|
+
nil
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
38
63
|
# connect to the host
|
|
39
64
|
def connect
|
|
40
|
-
try
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
65
|
+
#try three ways to connect to host (ip, vmhostname, hostname)
|
|
66
|
+
methods = []
|
|
67
|
+
if @ip
|
|
68
|
+
@ssh ||= connect_block(@ip, @user, @ssh_opts)
|
|
69
|
+
methods << "ip (#{@ip})"
|
|
70
|
+
end
|
|
71
|
+
if @vmhostname && !@ssh
|
|
72
|
+
@ssh ||= connect_block(@vmhostname, @user, @ssh_opts)
|
|
73
|
+
methods << "vmhostname (#{@vmhostname})"
|
|
74
|
+
end
|
|
75
|
+
if @hostname && !@ssh
|
|
76
|
+
@ssh ||= connect_block(@hostname, @user, @ssh_opts)
|
|
77
|
+
methods << "hostname (#{@hostname})"
|
|
78
|
+
end
|
|
79
|
+
if not @ssh
|
|
80
|
+
@logger.error "Failed to connect to #{@hostname}, attempted #{methods.join(', ')}"
|
|
81
|
+
raise RuntimeError, "Cannot connect to #{@hostname}"
|
|
82
|
+
end
|
|
83
|
+
@ssh
|
|
59
84
|
end
|
|
60
85
|
|
|
61
86
|
# closes this SshConnection
|
data/lib/beaker/test_case.rb
CHANGED
data/lib/beaker/version.rb
CHANGED
|
@@ -394,7 +394,6 @@ describe ClassMixedWithDSLHelpers do
|
|
|
394
394
|
allow( el_agent ).to receive( :puppet ).and_return( { 'vardir' => vardir } )
|
|
395
395
|
|
|
396
396
|
expect( el_agent ).to receive( :file_exist? ).with("/var/state/agent_catalog_run.lock").and_return(false)
|
|
397
|
-
expect( el_agent ).to receive( :file_exist? ).with("/etc/init.d/pe-puppet-agent").and_return(true)
|
|
398
397
|
|
|
399
398
|
expect( subject ).to receive( :puppet_resource ).with( "service", "puppet", "ensure=stopped").once
|
|
400
399
|
expect( subject ).to receive( :on ).once
|
|
@@ -29,12 +29,21 @@ describe ClassMixedWithDSLHelpers do
|
|
|
29
29
|
|
|
30
30
|
it "returns its second and third arguments concatenated." do
|
|
31
31
|
create_files(['destdir/name'])
|
|
32
|
-
result = subject.fetch_http_file "http://beaker.tool
|
|
32
|
+
result = subject.fetch_http_file "http://beaker.tool", "name", "destdir"
|
|
33
33
|
expect(result).to eq("destdir/name")
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
+
describe 'given invalid arguments' do
|
|
39
|
+
|
|
40
|
+
it 'chomps correctly when given a URL ending with a / character' do
|
|
41
|
+
expect( subject ).to receive( :open ).with( 'http://beaker.tool/name', anything )
|
|
42
|
+
subject.fetch_http_file( "http://beaker.tool/", "name", "destdir" )
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
end
|
|
46
|
+
|
|
38
47
|
end
|
|
39
48
|
|
|
40
49
|
describe "#fetch_http_dir" do
|