beaker 0.0.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 +15 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.simplecov +14 -0
- data/DOCUMENTING.md +167 -0
- data/Gemfile +3 -0
- data/LICENSE +17 -0
- data/README.md +332 -0
- data/Rakefile +121 -0
- data/beaker.gemspec +42 -0
- data/beaker.rb +10 -0
- data/bin/beaker +9 -0
- data/lib/beaker.rb +36 -0
- data/lib/beaker/answers.rb +29 -0
- data/lib/beaker/answers/version28.rb +104 -0
- data/lib/beaker/answers/version30.rb +194 -0
- data/lib/beaker/cli.rb +113 -0
- data/lib/beaker/command.rb +241 -0
- data/lib/beaker/command_factory.rb +21 -0
- data/lib/beaker/dsl.rb +85 -0
- data/lib/beaker/dsl/assertions.rb +87 -0
- data/lib/beaker/dsl/helpers.rb +625 -0
- data/lib/beaker/dsl/install_utils.rb +299 -0
- data/lib/beaker/dsl/outcomes.rb +99 -0
- data/lib/beaker/dsl/roles.rb +97 -0
- data/lib/beaker/dsl/structure.rb +63 -0
- data/lib/beaker/dsl/wrappers.rb +100 -0
- data/lib/beaker/host.rb +193 -0
- data/lib/beaker/host/aix.rb +15 -0
- data/lib/beaker/host/aix/file.rb +16 -0
- data/lib/beaker/host/aix/group.rb +35 -0
- data/lib/beaker/host/aix/user.rb +32 -0
- data/lib/beaker/host/unix.rb +54 -0
- data/lib/beaker/host/unix/exec.rb +15 -0
- data/lib/beaker/host/unix/file.rb +16 -0
- data/lib/beaker/host/unix/group.rb +40 -0
- data/lib/beaker/host/unix/pkg.rb +22 -0
- data/lib/beaker/host/unix/user.rb +32 -0
- data/lib/beaker/host/windows.rb +44 -0
- data/lib/beaker/host/windows/exec.rb +18 -0
- data/lib/beaker/host/windows/file.rb +15 -0
- data/lib/beaker/host/windows/group.rb +36 -0
- data/lib/beaker/host/windows/pkg.rb +26 -0
- data/lib/beaker/host/windows/user.rb +32 -0
- data/lib/beaker/hypervisor.rb +37 -0
- data/lib/beaker/hypervisor/aixer.rb +52 -0
- data/lib/beaker/hypervisor/blimper.rb +123 -0
- data/lib/beaker/hypervisor/fusion.rb +56 -0
- data/lib/beaker/hypervisor/solaris.rb +65 -0
- data/lib/beaker/hypervisor/vagrant.rb +118 -0
- data/lib/beaker/hypervisor/vcloud.rb +175 -0
- data/lib/beaker/hypervisor/vsphere.rb +80 -0
- data/lib/beaker/hypervisor/vsphere_helper.rb +200 -0
- data/lib/beaker/logger.rb +167 -0
- data/lib/beaker/network_manager.rb +73 -0
- data/lib/beaker/options_parsing.rb +323 -0
- data/lib/beaker/result.rb +55 -0
- data/lib/beaker/shared.rb +15 -0
- data/lib/beaker/shared/error_handler.rb +17 -0
- data/lib/beaker/shared/host_handler.rb +46 -0
- data/lib/beaker/shared/repetition.rb +28 -0
- data/lib/beaker/ssh_connection.rb +198 -0
- data/lib/beaker/test_case.rb +225 -0
- data/lib/beaker/test_config.rb +148 -0
- data/lib/beaker/test_suite.rb +288 -0
- data/lib/beaker/utils.rb +7 -0
- data/lib/beaker/utils/ntp_control.rb +42 -0
- data/lib/beaker/utils/repo_control.rb +92 -0
- data/lib/beaker/utils/setup_helper.rb +77 -0
- data/lib/beaker/utils/validator.rb +27 -0
- data/spec/beaker/command_spec.rb +94 -0
- data/spec/beaker/dsl/assertions_spec.rb +104 -0
- data/spec/beaker/dsl/helpers_spec.rb +230 -0
- data/spec/beaker/dsl/install_utils_spec.rb +70 -0
- data/spec/beaker/dsl/outcomes_spec.rb +43 -0
- data/spec/beaker/dsl/roles_spec.rb +86 -0
- data/spec/beaker/dsl/structure_spec.rb +60 -0
- data/spec/beaker/dsl/wrappers_spec.rb +52 -0
- data/spec/beaker/host_spec.rb +95 -0
- data/spec/beaker/logger_spec.rb +117 -0
- data/spec/beaker/options_parsing_spec.rb +37 -0
- data/spec/beaker/puppet_command_spec.rb +128 -0
- data/spec/beaker/ssh_connection_spec.rb +39 -0
- data/spec/beaker/test_case_spec.rb +6 -0
- data/spec/beaker/test_suite_spec.rb +44 -0
- data/spec/mocks_and_helpers.rb +34 -0
- data/spec/spec_helper.rb +15 -0
- metadata +359 -0
@@ -0,0 +1,323 @@
|
|
1
|
+
module Beaker
|
2
|
+
class Options
|
3
|
+
GITREPO = 'git://github.com/puppetlabs'
|
4
|
+
|
5
|
+
def self.options
|
6
|
+
return @options
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.repo?
|
10
|
+
GITREPO
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.parse_install_options(install_opts)
|
14
|
+
install_opts.map! { |opt|
|
15
|
+
case opt
|
16
|
+
when /^PUPPET\//
|
17
|
+
opt = "#{GITREPO}/puppet.git##{opt.split('/', 2)[1]}"
|
18
|
+
when /^FACTER\//
|
19
|
+
opt = "#{GITREPO}/facter.git##{opt.split('/', 2)[1]}"
|
20
|
+
when /^HIERA\//
|
21
|
+
opt = "#{GITREPO}/hiera.git##{opt.split('/', 2)[1]}"
|
22
|
+
when /^HIERA-PUPPET\//
|
23
|
+
opt = "#{GITREPO}/hiera-puppet.git##{opt.split('/', 2)[1]}"
|
24
|
+
end
|
25
|
+
opt
|
26
|
+
}
|
27
|
+
install_opts
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.file_list(paths)
|
31
|
+
files = []
|
32
|
+
if not paths.empty?
|
33
|
+
paths.each do |root|
|
34
|
+
if File.file? root then
|
35
|
+
files << root
|
36
|
+
else
|
37
|
+
discover_files = Dir.glob(
|
38
|
+
File.join(root, "**/*.rb")
|
39
|
+
).select { |f| File.file?(f) }
|
40
|
+
if discover_files.empty?
|
41
|
+
raise ArgumentError, "Empty directory used as an option (#{root})!"
|
42
|
+
end
|
43
|
+
files += discover_files
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
files
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.parse_args
|
51
|
+
return @options if @options
|
52
|
+
|
53
|
+
@no_args = ARGV.empty? ? true : false
|
54
|
+
|
55
|
+
@defaults = {}
|
56
|
+
@options = {}
|
57
|
+
@options_from_file = {}
|
58
|
+
|
59
|
+
optparse = OptionParser.new do|opts|
|
60
|
+
# Set a banner
|
61
|
+
opts.banner = "Usage: #{File.basename($0)} [options...]"
|
62
|
+
|
63
|
+
@defaults[:config] = nil
|
64
|
+
opts.on '-c', '--config FILE',
|
65
|
+
'Use configuration FILE' do |file|
|
66
|
+
@options[:config] = file
|
67
|
+
end
|
68
|
+
|
69
|
+
@defaults[:options_file] = nil
|
70
|
+
opts.on '-o', '--options-file FILE',
|
71
|
+
'Read options from FILE',
|
72
|
+
'This should evaluate to a ruby hash.',
|
73
|
+
'CLI optons are given precedence.' do |file|
|
74
|
+
@options_from_file = parse_options_file file
|
75
|
+
end
|
76
|
+
|
77
|
+
@defaults[:type] = 'pe'
|
78
|
+
opts.on '--type TYPE',
|
79
|
+
'one of git or pe',
|
80
|
+
'used to determine underlying path structure of puppet install',
|
81
|
+
'defaults to pe' do |type|
|
82
|
+
@options[:type] = type
|
83
|
+
end
|
84
|
+
|
85
|
+
@defaults[:helper] = []
|
86
|
+
opts.on '--helper PATH/TO/SCRIPT',
|
87
|
+
'Ruby file evaluated prior to tests',
|
88
|
+
'(a la spec_helper)' do |script|
|
89
|
+
@options[:helper] = []
|
90
|
+
if script.is_a?(Array)
|
91
|
+
@options[:helper] += script
|
92
|
+
elsif script =~ /,/
|
93
|
+
@options[:helper] += script.split(',')
|
94
|
+
else
|
95
|
+
@options[:helper] << script
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
@defaults[:load_path] = []
|
100
|
+
opts.on '--load-path /PATH/TO/DIR,/ADDITIONAL/DIR/PATHS',
|
101
|
+
'Add paths to LOAD_PATH' do |value|
|
102
|
+
@options[:load_path] = []
|
103
|
+
if value.is_a?(Array)
|
104
|
+
@options[:load_path] += value
|
105
|
+
elsif value =~ /,/
|
106
|
+
@options[:load_path] += value.split(',')
|
107
|
+
else
|
108
|
+
@options[:load_path] << value
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
@defaults[:tests] = []
|
113
|
+
opts.on '-t', '--tests /PATH/TO/DIR,/ADDITIONA/DIR/PATHS,/PATH/TO/FILE.rb',
|
114
|
+
'Execute tests from paths and files' do |value|
|
115
|
+
@options[:tests] = []
|
116
|
+
if value.is_a?(Array)
|
117
|
+
@options[:tests] += value
|
118
|
+
elsif value =~ /,/
|
119
|
+
@options[:tests] += value.split(',')
|
120
|
+
else
|
121
|
+
@options[:tests] << value
|
122
|
+
end
|
123
|
+
@options[:tests] = file_list(@options[:tests])
|
124
|
+
if @options[:tests].empty?
|
125
|
+
raise ArgumentError, "No tests to run!"
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
@defaults[:pre_suite] = []
|
130
|
+
opts.on '--pre-suite /PRE-SUITE/DIR/PATH,/ADDITIONAL/DIR/PATHS,/PATH/TO/FILE.rb',
|
131
|
+
'Path to project specific steps to be run BEFORE testing' do |value|
|
132
|
+
@options[:pre_suite] = []
|
133
|
+
if value.is_a?(Array)
|
134
|
+
@options[:pre_suite] += value
|
135
|
+
elsif value =~ /,/
|
136
|
+
@options[:pre_suite] += value.split(',')
|
137
|
+
else
|
138
|
+
@options[:pre_suite] << value
|
139
|
+
end
|
140
|
+
@options[:pre_suite] = file_list(@options[:pre_suite])
|
141
|
+
if @options[:pre_suite].empty?
|
142
|
+
raise ArgumentError, "Empty pre-suite!"
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
@defaults[:post_suite] = []
|
147
|
+
opts.on '--post-suite /POST-SUITE/DIR/PATH,/OPTIONAL/ADDITONAL/DIR/PATHS,/PATH/TO/FILE.rb',
|
148
|
+
'Path to project specific steps to be run AFTER testing' do |value|
|
149
|
+
@options[:post_suite] = []
|
150
|
+
if value.is_a?(Array)
|
151
|
+
@options[:post_suite] += value
|
152
|
+
elsif value =~ /,/
|
153
|
+
@options[:post_suite] += value.split(',')
|
154
|
+
else
|
155
|
+
@options[:post_suite] << value
|
156
|
+
end
|
157
|
+
@options[:post_suite] = file_list(@options[:post_suite])
|
158
|
+
if @options[:post_suite].empty?
|
159
|
+
raise ArgumentError, "Empty post-suite!"
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
@defaults[:provision] = true
|
164
|
+
opts.on '--[no-]provision',
|
165
|
+
'Do not provision vm images before testing',
|
166
|
+
'(default: true)' do |bool|
|
167
|
+
@options[:provision] = bool
|
168
|
+
end
|
169
|
+
|
170
|
+
@defaults[:preserve_hosts] = false
|
171
|
+
opts.on '--[no-]preserve-hosts',
|
172
|
+
'Preserve cloud instances' do |value|
|
173
|
+
@options[:preserve_hosts] = value
|
174
|
+
end
|
175
|
+
|
176
|
+
@defaults[:root_keys] = false
|
177
|
+
opts.on '--root-keys',
|
178
|
+
'Install puppetlabs pubkeys for superuser',
|
179
|
+
'(default: false)' do |bool|
|
180
|
+
@options[:root_keys] = bool
|
181
|
+
end
|
182
|
+
|
183
|
+
@defaults[:keyfile] = "#{ENV['HOME']}/.ssh/id_rsa"
|
184
|
+
opts.on '--keyfile /PATH/TO/SSH/KEY',
|
185
|
+
'Specify alternate SSH key',
|
186
|
+
'(default: ~/.ssh/id_rsa)' do |key|
|
187
|
+
@options[:keyfile] = key
|
188
|
+
end
|
189
|
+
|
190
|
+
|
191
|
+
@defaults[:install] = []
|
192
|
+
opts.on '-i URI', '--install URI',
|
193
|
+
'Install a project repo/app on the SUTs',
|
194
|
+
'Provide full git URI or use short form KEYWORD/name',
|
195
|
+
'supported keywords: PUPPET, FACTER, HIERA, HIERA-PUPPET' do |value|
|
196
|
+
@options[:install] = []
|
197
|
+
if value.is_a?(Array)
|
198
|
+
@options[:install] += value
|
199
|
+
elsif value =~ /,/
|
200
|
+
@options[:install] += value.split(',')
|
201
|
+
else
|
202
|
+
@options[:install] << value
|
203
|
+
end
|
204
|
+
@options[:install] = parse_install_options(@options[:install])
|
205
|
+
end
|
206
|
+
|
207
|
+
@defaults[:modules] = []
|
208
|
+
opts.on('-m', '--modules URI', 'Select puppet module git install URI') do |value|
|
209
|
+
@options[:modules] ||= []
|
210
|
+
@options[:modules] << value
|
211
|
+
end
|
212
|
+
|
213
|
+
@defaults[:quiet] = false
|
214
|
+
opts.on '-q', '--[no-]quiet',
|
215
|
+
'Do not log output to STDOUT',
|
216
|
+
'(default: false)' do |bool|
|
217
|
+
@options[:quiet] = bool
|
218
|
+
end
|
219
|
+
|
220
|
+
@defaults[:xml] = false
|
221
|
+
opts.on '-x', '--[no-]xml',
|
222
|
+
'Emit JUnit XML reports on tests',
|
223
|
+
'(default: false)' do |bool|
|
224
|
+
@options[:xml] = bool
|
225
|
+
end
|
226
|
+
|
227
|
+
@defaults[:color] = true
|
228
|
+
opts.on '--[no-]color',
|
229
|
+
'Do not display color in log output',
|
230
|
+
'(default: true)' do |bool|
|
231
|
+
@options[:color] = bool
|
232
|
+
end
|
233
|
+
|
234
|
+
@defaults[:debug] = false
|
235
|
+
opts.on '--[no-]debug',
|
236
|
+
'Enable full debugging',
|
237
|
+
'(default: false)' do |bool|
|
238
|
+
@options[:debug] = bool
|
239
|
+
end
|
240
|
+
|
241
|
+
@defaults[:dry_run] = false
|
242
|
+
opts.on '-d', '--[no-]dry-run',
|
243
|
+
'Report what would happen on targets',
|
244
|
+
'(default: false)' do |bool|
|
245
|
+
@options[:dry_run] = bool
|
246
|
+
$dry_run = bool
|
247
|
+
end
|
248
|
+
|
249
|
+
@defaults[:fail_mode] = nil
|
250
|
+
opts.on '--fail-mode [MODE]',
|
251
|
+
'How should the harness react to errors/failures',
|
252
|
+
'Possible values:',
|
253
|
+
'fast (skip all subsequent tests, cleanup, exit)',
|
254
|
+
'stop (skip all subsequent tests, do no cleanup, exit immediately)' do |mode|
|
255
|
+
@options[:fail_mode] = mode
|
256
|
+
end
|
257
|
+
|
258
|
+
@defaults[:timesync] = false
|
259
|
+
opts.on '--[no-]ntp',
|
260
|
+
'Sync time on SUTs before testing',
|
261
|
+
'(default: false)' do |bool|
|
262
|
+
@options[:timesync] = bool
|
263
|
+
end
|
264
|
+
|
265
|
+
@defaults[:repo_proxy] = false
|
266
|
+
opts.on '--repo-proxy',
|
267
|
+
'Proxy packaging repositories on ubuntu, debian and solaris-11',
|
268
|
+
'(default: false)' do
|
269
|
+
@options[:repo_proxy] = true
|
270
|
+
end
|
271
|
+
|
272
|
+
@defaults[:add_el_extras] = false
|
273
|
+
opts.on '--add-el-extras',
|
274
|
+
'Add Extra Packages for Enterprise Linux (EPEL) repository to el-* hosts',
|
275
|
+
'(default: false)' do
|
276
|
+
@options[:add_el_extras] = true
|
277
|
+
end
|
278
|
+
|
279
|
+
opts.on('--help', 'Display this screen' ) do |yes|
|
280
|
+
puts opts
|
281
|
+
exit
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
optparse.parse!
|
286
|
+
|
287
|
+
# We have use the @no_args var because OptParse consumes ARGV as it parses
|
288
|
+
# so we have to check the value of ARGV at the begining of the method,
|
289
|
+
# let the options be set, then output usage.
|
290
|
+
puts optparse if @no_args
|
291
|
+
|
292
|
+
# merge in the options that we read from the file
|
293
|
+
@options = @options_from_file.merge(@options)
|
294
|
+
# merge in defaults
|
295
|
+
@options = @defaults.merge(@options)
|
296
|
+
|
297
|
+
if @options[:type] !~ /(pe)|(git)/
|
298
|
+
raise ArgumentError.new("--type must be one of pe or git, not '#{@options[:type]}'")
|
299
|
+
end
|
300
|
+
|
301
|
+
raise ArgumentError.new("--fail-mode must be one of fast, stop") unless ["fast", "stop", nil].include?(@options[:fail_mode])
|
302
|
+
|
303
|
+
@options
|
304
|
+
end
|
305
|
+
|
306
|
+
def self.parse_options_file(options_file_path)
|
307
|
+
options_file_path = File.expand_path(options_file_path)
|
308
|
+
unless File.exists?(options_file_path)
|
309
|
+
raise ArgumentError, "Specified options file '#{options_file_path}' does not exist!"
|
310
|
+
end
|
311
|
+
# This eval will allow the specified options file to have access to our
|
312
|
+
# scope. It is important that the variable 'options_file_path' is
|
313
|
+
# accessible, because some existing options files (e.g. puppetdb) rely on
|
314
|
+
# that variable to determine their own location (for use in 'require's, etc.)
|
315
|
+
result = eval(File.read(options_file_path))
|
316
|
+
unless result.is_a? Hash
|
317
|
+
raise ArgumentError, "Options file '#{options_file_path}' must return a hash!"
|
318
|
+
end
|
319
|
+
|
320
|
+
result
|
321
|
+
end
|
322
|
+
end
|
323
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Beaker
|
2
|
+
class Result
|
3
|
+
attr_accessor :host, :cmd, :exit_code, :stdout, :stderr, :output,
|
4
|
+
:raw_stdout, :raw_stderr, :raw_output
|
5
|
+
def initialize(host, cmd)
|
6
|
+
@host = host
|
7
|
+
@cmd = cmd
|
8
|
+
@stdout = ''
|
9
|
+
@stderr = ''
|
10
|
+
@output = ''
|
11
|
+
@exit_code = nil
|
12
|
+
end
|
13
|
+
|
14
|
+
# Ruby assumes chunked data (like something it receives from Net::SSH)
|
15
|
+
# to be binary (ASCII-8BIT). We need to gather all chunked data and then
|
16
|
+
# re-encode it as the default encoding it assumes for external text
|
17
|
+
# (ie our test files and the strings they're trying to match Net::SSH's
|
18
|
+
# output from)
|
19
|
+
# This is also the lowest overhead place to normalize line endings, IIRC
|
20
|
+
def finalize!
|
21
|
+
@raw_stdout = @stdout
|
22
|
+
@stdout = normalize_line_endings( convert( @stdout ) )
|
23
|
+
@raw_stderr = @stderr
|
24
|
+
@stderr = normalize_line_endings( convert( @stderr ) )
|
25
|
+
@raw_output = @output
|
26
|
+
@output = normalize_line_endings( convert( @output ) )
|
27
|
+
end
|
28
|
+
|
29
|
+
def normalize_line_endings string
|
30
|
+
return string.gsub(/\r\n?/, "\n")
|
31
|
+
end
|
32
|
+
|
33
|
+
def convert string
|
34
|
+
if string.respond_to?( :force_encoding ) and defined?( Encoding )
|
35
|
+
# We're running in >= 1.9 and we'll need to convert
|
36
|
+
return string.force_encoding( Encoding.default_external )
|
37
|
+
else
|
38
|
+
# We're running in < 1.9 and Ruby doesn't care
|
39
|
+
return string
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def log(logger)
|
44
|
+
logger.debug "Exited: #{exit_code}" unless exit_code == 0
|
45
|
+
end
|
46
|
+
|
47
|
+
def formatted_output(limit=10)
|
48
|
+
@output.split("\n").last(limit).collect {|x| "\t" + x}.join("\n")
|
49
|
+
end
|
50
|
+
|
51
|
+
def exit_code_in?(range)
|
52
|
+
range.include?(@exit_code)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
[ 'repetition', 'error_handler', 'host_handler' ].each do |file|
|
2
|
+
begin
|
3
|
+
require "beaker/shared/#{file}"
|
4
|
+
rescue LoadError
|
5
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'shared', file))
|
6
|
+
end
|
7
|
+
end
|
8
|
+
module Beaker
|
9
|
+
module Shared
|
10
|
+
include Beaker::Shared::ErrorHandler
|
11
|
+
include Beaker::Shared::HostHandler
|
12
|
+
include Beaker::Shared::Repetition
|
13
|
+
end
|
14
|
+
end
|
15
|
+
include Beaker::Shared
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Beaker
|
2
|
+
module Shared
|
3
|
+
module ErrorHandler
|
4
|
+
|
5
|
+
def report_and_raise(logger, e, msg)
|
6
|
+
logger.error "Failed: errored in #{msg}"
|
7
|
+
logger.error(e.inspect)
|
8
|
+
bt = e.backtrace
|
9
|
+
logger.pretty_backtrace(bt).each_line do |line|
|
10
|
+
logger.error(line)
|
11
|
+
end
|
12
|
+
raise e
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Beaker
|
2
|
+
module Shared
|
3
|
+
module HostHandler
|
4
|
+
|
5
|
+
# NOTE: this code is shamelessly stolen from facter's 'domain' fact, but
|
6
|
+
# we don't have access to facter at this point in the run. Also, this
|
7
|
+
# utility method should perhaps be moved to a more central location in the
|
8
|
+
# framework.
|
9
|
+
def get_domain_name(host)
|
10
|
+
domain = nil
|
11
|
+
search = nil
|
12
|
+
resolv_conf = host.exec(Command.new("cat /etc/resolv.conf")).stdout
|
13
|
+
resolv_conf.each_line { |line|
|
14
|
+
if line =~ /^\s*domain\s+(\S+)/
|
15
|
+
domain = $1
|
16
|
+
elsif line =~ /^\s*search\s+(\S+)/
|
17
|
+
search = $1
|
18
|
+
end
|
19
|
+
}
|
20
|
+
return domain if domain
|
21
|
+
return search if search
|
22
|
+
end
|
23
|
+
|
24
|
+
def get_ip(host)
|
25
|
+
host.exec(Command.new("ip a|awk '/g/{print$2}' | cut -d/ -f1 | head -1")).stdout.chomp
|
26
|
+
end
|
27
|
+
|
28
|
+
def set_etc_hosts(host, etc_hosts)
|
29
|
+
host.exec(Command.new("echo '#{etc_hosts}' > /etc/hosts"))
|
30
|
+
end
|
31
|
+
|
32
|
+
def hosts_with_role(hosts, desired_role = nil)
|
33
|
+
hosts.select do |host|
|
34
|
+
desired_role.nil? or host['roles'].include?(desired_role.to_s)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def only_host_with_role(hosts, role)
|
39
|
+
a_host = hosts_with_role(hosts, role)
|
40
|
+
raise "There can be only one #{role}, but I found:" +
|
41
|
+
"#{a_host.map {|h| h.to_s } }" unless a_host.length == 1
|
42
|
+
a_host.first
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|