beaker 0.0.0 → 1.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.
Files changed (98) hide show
  1. checksums.yaml +8 -8
  2. data/.travis.yml +8 -0
  3. data/README.md +6 -6
  4. data/beaker.gemspec +6 -2
  5. data/lib/beaker.rb +1 -1
  6. data/lib/beaker/answers.rb +34 -7
  7. data/lib/beaker/answers/version20.rb +124 -0
  8. data/lib/beaker/answers/version28.rb +21 -0
  9. data/lib/beaker/answers/version30.rb +24 -5
  10. data/lib/beaker/cli.rb +55 -41
  11. data/lib/beaker/command.rb +2 -2
  12. data/lib/beaker/dsl/helpers.rb +320 -106
  13. data/lib/beaker/dsl/install_utils.rb +202 -81
  14. data/lib/beaker/dsl/roles.rb +40 -0
  15. data/lib/beaker/host.rb +28 -20
  16. data/lib/beaker/host/unix.rb +7 -4
  17. data/lib/beaker/host/unix/pkg.rb +42 -12
  18. data/lib/beaker/host/windows.rb +9 -5
  19. data/lib/beaker/host/windows/group.rb +1 -1
  20. data/lib/beaker/host/windows/pkg.rb +41 -8
  21. data/lib/beaker/hypervisor.rb +23 -10
  22. data/lib/beaker/hypervisor/aixer.rb +15 -19
  23. data/lib/beaker/hypervisor/blimper.rb +71 -72
  24. data/lib/beaker/hypervisor/fusion.rb +11 -10
  25. data/lib/beaker/hypervisor/solaris.rb +17 -23
  26. data/lib/beaker/hypervisor/vagrant.rb +27 -12
  27. data/lib/beaker/hypervisor/vcloud.rb +154 -138
  28. data/lib/beaker/hypervisor/vcloud_pooled.rb +97 -0
  29. data/lib/beaker/hypervisor/vsphere.rb +8 -5
  30. data/lib/beaker/hypervisor/vsphere_helper.rb +43 -33
  31. data/lib/beaker/network_manager.rb +16 -12
  32. data/lib/beaker/options/command_line_parser.rb +199 -0
  33. data/lib/beaker/options/hosts_file_parser.rb +39 -0
  34. data/lib/beaker/options/options_file_parser.rb +45 -0
  35. data/lib/beaker/options/options_hash.rb +294 -0
  36. data/lib/beaker/options/parser.rb +288 -0
  37. data/lib/beaker/options/pe_version_scraper.rb +35 -0
  38. data/lib/beaker/options/presets.rb +70 -0
  39. data/lib/beaker/shared.rb +2 -1
  40. data/lib/beaker/shared/host_handler.rb +7 -2
  41. data/lib/beaker/shared/repetition.rb +1 -0
  42. data/lib/beaker/shared/timed.rb +14 -0
  43. data/lib/beaker/test_case.rb +2 -38
  44. data/lib/beaker/test_suite.rb +11 -25
  45. data/lib/beaker/utils/repo_control.rb +6 -8
  46. data/lib/beaker/utils/setup_helper.rb +9 -20
  47. data/spec/beaker/answers_spec.rb +109 -0
  48. data/spec/beaker/command_spec.rb +2 -2
  49. data/spec/beaker/dsl/assertions_spec.rb +1 -3
  50. data/spec/beaker/dsl/helpers_spec.rb +519 -84
  51. data/spec/beaker/dsl/install_utils_spec.rb +265 -16
  52. data/spec/beaker/dsl/roles_spec.rb +31 -10
  53. data/spec/beaker/host/windows/group_spec.rb +55 -0
  54. data/spec/beaker/host_spec.rb +130 -40
  55. data/spec/beaker/hypervisor/aixer_spec.rb +34 -0
  56. data/spec/beaker/hypervisor/blimper_spec.rb +77 -0
  57. data/spec/beaker/hypervisor/fusion_spec.rb +26 -0
  58. data/spec/beaker/hypervisor/hypervisor_spec.rb +66 -0
  59. data/spec/beaker/hypervisor/solaris_spec.rb +39 -0
  60. data/spec/beaker/hypervisor/vagrant_spec.rb +105 -0
  61. data/spec/beaker/hypervisor/vcloud_pooled_spec.rb +60 -0
  62. data/spec/beaker/hypervisor/vcloud_spec.rb +70 -0
  63. data/spec/beaker/hypervisor/vsphere_helper_spec.rb +162 -0
  64. data/spec/beaker/hypervisor/vsphere_spec.rb +76 -0
  65. data/spec/beaker/options/command_line_parser_spec.rb +25 -0
  66. data/spec/beaker/options/data/LATEST +1 -0
  67. data/spec/beaker/options/data/badyaml.cfg +21 -0
  68. data/spec/beaker/options/data/hosts.cfg +21 -0
  69. data/spec/beaker/options/data/opts.txt +6 -0
  70. data/spec/beaker/options/hosts_file_parser_spec.rb +30 -0
  71. data/spec/beaker/options/options_file_parser_spec.rb +23 -0
  72. data/spec/beaker/options/options_hash_spec.rb +111 -0
  73. data/spec/beaker/options/parser_spec.rb +172 -0
  74. data/spec/beaker/options/pe_version_scaper_spec.rb +15 -0
  75. data/spec/beaker/options/presets_spec.rb +24 -0
  76. data/spec/beaker/puppet_command_spec.rb +54 -21
  77. data/spec/beaker/shared/error_handler_spec.rb +40 -0
  78. data/spec/beaker/shared/host_handler_spec.rb +104 -0
  79. data/spec/beaker/shared/repetition_spec.rb +72 -0
  80. data/spec/beaker/test_suite_spec.rb +3 -16
  81. data/spec/beaker/utils/ntp_control_spec.rb +42 -0
  82. data/spec/beaker/utils/repo_control_spec.rb +168 -0
  83. data/spec/beaker/utils/setup_helper_spec.rb +82 -0
  84. data/spec/beaker/utils/validator_spec.rb +58 -0
  85. data/spec/helpers.rb +97 -0
  86. data/spec/matchers.rb +39 -0
  87. data/spec/mock_blimpy.rb +48 -0
  88. data/spec/mock_fission.rb +60 -0
  89. data/spec/mock_vsphere.rb +310 -0
  90. data/spec/mock_vsphere_helper.rb +183 -0
  91. data/spec/mocks.rb +83 -0
  92. data/spec/spec_helper.rb +8 -1
  93. metadata +106 -13
  94. data/beaker.rb +0 -10
  95. data/lib/beaker/options_parsing.rb +0 -323
  96. data/lib/beaker/test_config.rb +0 -148
  97. data/spec/beaker/options_parsing_spec.rb +0 -37
  98. data/spec/mocks_and_helpers.rb +0 -34
@@ -0,0 +1,97 @@
1
+ require 'yaml' unless defined?(YAML)
2
+ require 'json'
3
+ require 'net/http'
4
+
5
+ module Beaker
6
+ class VcloudPooled < Beaker::Hypervisor
7
+ CHARMAP = [('a'..'z'),('0'..'9')].map{|r| r.to_a}.flatten
8
+ SSH_EXCEPTIONS = [
9
+ SocketError,
10
+ Timeout::Error,
11
+ Errno::ETIMEDOUT,
12
+ Errno::EHOSTDOWN,
13
+ Errno::EHOSTUNREACH,
14
+ Errno::ECONNREFUSED,
15
+ Errno::ECONNRESET,
16
+ Errno::ENETUNREACH,
17
+ ]
18
+
19
+ def initialize(vcloud_hosts, options)
20
+ @options = options
21
+ @logger = options[:logger]
22
+ @vcloud_hosts = vcloud_hosts
23
+
24
+ raise 'You must specify a datastore for vCloud instances!' unless @options['datastore']
25
+ raise 'You must specify a resource pool for vCloud instances!' unless @options['resourcepool']
26
+ raise 'You must specify a folder for vCloud instances!' unless @options['folder']
27
+ end
28
+
29
+ def provision
30
+ start = Time.now
31
+ try = 1
32
+ @vcloud_hosts.each_with_index do |h, i|
33
+ if h['template'] =~ /\//
34
+ templatefolders = h['template'].split('/')
35
+ h['template'] = templatefolders.pop
36
+ end
37
+
38
+ @logger.notify "Requesting '#{h['template']}' VM from vCloud host pool"
39
+
40
+ begin
41
+ uri = URI.parse(@options['pooling_api']+'/vm/'+h['template'])
42
+
43
+ http = Net::HTTP.new( uri.host, uri.port )
44
+ request = Net::HTTP::Post.new(uri.request_uri)
45
+
46
+ request.set_form_data({'pool' => @options['resourcepool'], 'folder' => 'foo'})
47
+
48
+ attempts = @options[:timeout].to_i / 5
49
+ response = http.request(request)
50
+ parsed_response = JSON.parse(response.body)
51
+ if parsed_response[h['template']] && parsed_response[h['template']]['ok'] && parsed_response[h['template']]['hostname']
52
+ h['vmhostname'] = parsed_response[h['template']]['hostname']
53
+ else
54
+ raise "VcloudPooled.provision - no vCloud host free for #{h.name} in pool"
55
+ end
56
+ rescue JSON::ParserError, RuntimeError, *SSH_EXCEPTIONS => e
57
+ if try <= attempts
58
+ sleep 5
59
+ try += 1
60
+ retry
61
+ end
62
+ report_and_raise(@logger, e, 'vCloudPooled.provision')
63
+ end
64
+
65
+ @logger.notify "Using available vCloud host '#{h['vmhostname']}' (#{h.name})"
66
+ end
67
+
68
+ @logger.notify 'Spent %.2f seconds grabbing VMs' % (Time.now - start)
69
+ end
70
+
71
+ def cleanup
72
+ vm_names = @vcloud_hosts.map {|h| h['vmhostname'] }.compact
73
+ if @vcloud_hosts.length != vm_names.length
74
+ @logger.warn "Some hosts did not have vmhostname set correctly! This likely means VM provisioning was not successful"
75
+ end
76
+
77
+ start = Time.now
78
+ vm_names.each do |name|
79
+ @logger.notify "Handing '#{name}' back to pooling API for VM destruction"
80
+
81
+ uri = URI.parse(@options['pooling_api']+'/vm/'+name)
82
+
83
+ http = Net::HTTP.new( uri.host, uri.port )
84
+ request = Net::HTTP::Delete.new(uri.request_uri)
85
+
86
+ begin
87
+ response = http.request(request)
88
+ rescue *SSH_EXCEPTIONS => e
89
+ report_and_raise(@logger, e, 'vCloudPooled.cleanup (http.request)')
90
+ end
91
+ end
92
+
93
+ @logger.notify "Spent %.2f seconds cleaning up" % (Time.now - start)
94
+ end
95
+
96
+ end
97
+ end
@@ -1,13 +1,16 @@
1
+ require 'yaml' unless defined?(YAML)
2
+
1
3
  module Beaker
2
4
  class Vsphere < Beaker::Hypervisor
3
5
 
4
- def initialize(vsphere_hosts, options, config)
6
+ def initialize(vsphere_hosts, options)
5
7
  @options = options
6
- @@config = config['CONFIG'].dup
7
8
  @logger = options[:logger]
8
9
  @vsphere_hosts = vsphere_hosts
9
- require 'yaml' unless defined?(YAML)
10
- vsphere_credentials = VsphereHelper.load_config
10
+ end
11
+
12
+ def provision
13
+ vsphere_credentials = VsphereHelper.load_config(@options[:dot_fog])
11
14
 
12
15
  @logger.notify "Connecting to vSphere at #{vsphere_credentials[:server]}" +
13
16
  " with credentials for #{vsphere_credentials[:user]}"
@@ -50,7 +53,7 @@ module Beaker
50
53
 
51
54
  def cleanup
52
55
  @logger.notify "Destroying vsphere boxes"
53
- vsphere_credentials = VsphereHelper.load_config
56
+ vsphere_credentials = VsphereHelper.load_config(@options[:dot_fog])
54
57
 
55
58
  @logger.notify "Connecting to vSphere at #{vsphere_credentials[:server]}" +
56
59
  " with credentials for #{vsphere_credentials[:user]}"
@@ -1,5 +1,5 @@
1
1
  require 'yaml' unless defined?(YAML)
2
- require 'rubygems' unless defined?(Gem)
2
+ require 'rbvmomi'
3
3
  begin
4
4
  require 'beaker/logger'
5
5
  rescue LoadError
@@ -7,35 +7,29 @@ rescue LoadError
7
7
  end
8
8
 
9
9
  class VsphereHelper
10
- def initialize vInfo = {}
10
+ def initialize vInfo
11
11
  @logger = vInfo[:logger] || Beaker::Logger.new
12
- begin
13
- require 'rbvmomi'
14
- rescue LoadError
15
- raise "Unable to load RbVmomi, please ensure its installed"
16
- end
17
12
  @connection = RbVmomi::VIM.connect :host => vInfo[:server],
18
13
  :user => vInfo[:user],
19
14
  :password => vInfo[:pass],
20
15
  :insecure => true
21
16
  end
22
17
 
23
- def self.load_config
18
+ def self.load_config(dot_fog = '.fog')
24
19
  # support Fog/Cloud Provisioner layout
25
20
  # (ie, someplace besides my made up conf)
26
21
  vsphere_credentials = nil
27
- if File.exists? '/etc/plharness/vsphere'
28
- vsphere_credentials = load_legacy_credentials
29
-
30
- elsif File.exists?( File.join(ENV['HOME'], '.fog') )
31
- vsphere_credentials = load_fog_credentials
22
+ if File.exists?( dot_fog )
23
+ vsphere_credentials = load_fog_credentials(dot_fog)
24
+ else
25
+ raise ArgumentError, ".fog file '#{dot_fog}' does not exist"
32
26
  end
33
27
 
34
28
  return vsphere_credentials
35
29
  end
36
30
 
37
- def self.load_fog_credentials
38
- vInfo = YAML.load_file( File.join(ENV['HOME'], '.fog') )
31
+ def self.load_fog_credentials(dot_fog = '.fog')
32
+ vInfo = YAML.load_file( dot_fog )
39
33
 
40
34
  vsphere_credentials = {}
41
35
  vsphere_credentials[:server] = vInfo[:default][:vsphere_server]
@@ -45,24 +39,6 @@ class VsphereHelper
45
39
  return vsphere_credentials
46
40
  end
47
41
 
48
- def self.load_legacy_credentials
49
- vInfo = YAML.load_file '/etc/plharness/vsphere'
50
-
51
- puts(
52
- "Use of /etc/plharness/vsphere as a config file is deprecated.\n" +
53
- "Please use ~/.fog instead\n" +
54
- "See http://docs.puppetlabs.com/pe/2.0/" +
55
- "cloudprovisioner_configuring.html for format"
56
- )
57
-
58
- vsphere_credentials = {}
59
- vsphere_credentials[:server] = vInfo['location']
60
- vsphere_credentials[:user] = vInfo['user']
61
- vsphere_credentials[:pass] = vInfo['pass']
62
-
63
- return vsphere_credentials
64
- end
65
-
66
42
  def find_snapshot vm, snapname
67
43
  search_child_snaps vm.snapshot.rootSnapshotList, snapname
68
44
  end
@@ -193,6 +169,40 @@ class VsphereHelper
193
169
  })
194
170
  end
195
171
 
172
+ def wait_for_tasks tasks, try, attempts
173
+ obj_set = tasks.map { |task| { :obj => task } }
174
+ filter = @connection.propertyCollector.CreateFilter(
175
+ :spec => {
176
+ :propSet => [{ :type => 'Task',
177
+ :all => false,
178
+ :pathSet => ['info.state']}],
179
+ :objectSet => obj_set
180
+ },
181
+ :partialUpdates => false
182
+ )
183
+ ver = ''
184
+ while true
185
+ result = @connection.propertyCollector.WaitForUpdates(:version => ver)
186
+ ver = result.version
187
+ complete = 0
188
+ tasks.each do |task|
189
+ if ['success', 'error'].member? task.info.state
190
+ complete += 1
191
+ end
192
+ end
193
+ break if (complete == tasks.length)
194
+ if try <= attempts
195
+ sleep 5
196
+ try += 1
197
+ else
198
+ raise "unable to complete Vsphere tasks before timeout"
199
+ end
200
+ end
201
+
202
+ filter.DestroyPropertyFilter
203
+ tasks
204
+ end
205
+
196
206
  def close
197
207
  @connection.close
198
208
  end
@@ -10,15 +10,18 @@ module Beaker
10
10
  class NetworkManager
11
11
  HYPERVISOR_TYPES = ['solaris', 'blimpy', 'vsphere', 'fusion', 'aix', 'vcloud', 'vagrant']
12
12
 
13
- def initialize(config, options, logger)
13
+ def initialize(options, logger)
14
14
  @logger = logger
15
15
  @options = options
16
16
  @hosts = []
17
- @config = config
18
17
  @virtual_machines = {}
19
18
  @noprovision_machines = []
20
- @config['HOSTS'].each_key do |name|
21
- host_info = @config['HOSTS'][name]
19
+ end
20
+
21
+ def provision
22
+ #sort hosts into those to be provisioned and those to use non-provisioned
23
+ @options['HOSTS'].each_key do |name|
24
+ host_info = @options['HOSTS'][name]
22
25
  #check to see if this host has a hypervisor
23
26
  hypervisor = host_info['hypervisor']
24
27
  #provision this box
@@ -34,24 +37,21 @@ module Beaker
34
37
  @logger.debug "No hypervisor for #{name}, connecting to host without provisioning"
35
38
  @noprovision_machines << name
36
39
  end
37
-
38
40
  end
39
- end
40
41
 
41
- def provision
42
42
  @provisioned_set = {}
43
43
  @virtual_machines.each do |type, names|
44
44
  hosts_for_type = []
45
45
  #set up host objects for provisioned provisioned_set
46
46
  names.each do |name|
47
- host = Beaker::Host.create(name, @options, @config)
47
+ host = Beaker::Host.create(name, @options)
48
48
  hosts_for_type << host
49
49
  end
50
- @provisioned_set[type] = Beaker::Hypervisor.create(type, hosts_for_type, @options, @config)
50
+ @provisioned_set[type] = Beaker::Hypervisor.create(type, hosts_for_type, @options)
51
51
  @hosts << hosts_for_type
52
52
  end
53
53
  @noprovision_machines.each do |name|
54
- @hosts << Beaker::Host.create(name, @options, @config)
54
+ @hosts << Beaker::Host.create(name, @options)
55
55
  end
56
56
  @hosts = @hosts.flatten
57
57
  @hosts
@@ -63,8 +63,12 @@ module Beaker
63
63
  @hosts.each {|host| host.close }
64
64
 
65
65
  if not @options[:preserve_hosts]
66
- @provisioned_set.each_key do |type|
67
- @provisioned_set[type].cleanup
66
+ if @provisioned_set
67
+ @provisioned_set.each_key do |type|
68
+ if @provisioned_set[type]
69
+ @provisioned_set[type].cleanup
70
+ end
71
+ end
68
72
  end
69
73
  end
70
74
  end
@@ -0,0 +1,199 @@
1
+ module Beaker
2
+ module Options
3
+ #An object that parses arguments in the format ['--option', 'value', '--option2', 'value2', '--switch']
4
+ class CommandLineParser
5
+
6
+ # @example Create a CommanLineParser
7
+ # a = CommandLineParser.new
8
+ #
9
+ # @note All of Beaker's supported command line options are defined here
10
+ def initialize
11
+ @cmd_options = Beaker::Options::OptionsHash.new
12
+
13
+ @optparse = OptionParser.new do|opts|
14
+ # Set a banner
15
+ opts.banner = "Usage: #{File.basename($0)} [options...]"
16
+
17
+ opts.on '-h', '--hosts FILE',
18
+ 'Use host configuration FILE',
19
+ '(default sample.cfg)' do |file|
20
+ @cmd_options[:hosts_file] = file
21
+ end
22
+
23
+ opts.on '-o', '--options-file FILE',
24
+ 'Read options from FILE',
25
+ 'This should evaluate to a ruby hash.',
26
+ 'CLI optons are given precedence.' do |file|
27
+ @cmd_options[:options_file] = file
28
+ end
29
+
30
+ opts.on '--type TYPE',
31
+ 'one of git or pe',
32
+ 'used to determine underlying path structure of puppet install',
33
+ '(default pe)' do |type|
34
+ @cmd_options[:type] = type
35
+ end
36
+
37
+ opts.on '--helper PATH/TO/SCRIPT',
38
+ 'Ruby file evaluated prior to tests',
39
+ '(a la spec_helper)' do |script|
40
+ @cmd_options[:helper] = script
41
+ end
42
+
43
+ opts.on '--load-path /PATH/TO/DIR,/ADDITIONAL/DIR/PATHS',
44
+ 'Add paths to LOAD_PATH' do |value|
45
+ @cmd_options[:load_path] = value
46
+ end
47
+
48
+ opts.on '-t', '--tests /PATH/TO/DIR,/ADDITIONA/DIR/PATHS,/PATH/TO/FILE.rb',
49
+ 'Execute tests from paths and files' do |value|
50
+ @cmd_options[:tests] = value
51
+ end
52
+
53
+ opts.on '--pre-suite /PRE-SUITE/DIR/PATH,/ADDITIONAL/DIR/PATHS,/PATH/TO/FILE.rb',
54
+ 'Path to project specific steps to be run BEFORE testing' do |value|
55
+ @cmd_options[:pre_suite] = value
56
+ end
57
+
58
+ opts.on '--post-suite /POST-SUITE/DIR/PATH,/OPTIONAL/ADDITONAL/DIR/PATHS,/PATH/TO/FILE.rb',
59
+ 'Path to project specific steps to be run AFTER testing' do |value|
60
+ @cmd_options[:post_suite] = value
61
+ end
62
+
63
+ opts.on '--[no-]provision',
64
+ 'Do not provision vm images before testing',
65
+ '(default: true)' do |bool|
66
+ @cmd_options[:provision] = bool
67
+ end
68
+
69
+ opts.on '--[no-]preserve-hosts',
70
+ 'Preserve cloud instances' do |value|
71
+ @cmd_options[:preserve_hosts] = value
72
+ end
73
+
74
+ opts.on '--root-keys',
75
+ 'Install puppetlabs pubkeys for superuser',
76
+ '(default: false)' do |bool|
77
+ @cmd_options[:root_keys] = bool
78
+ end
79
+
80
+ opts.on '--keyfile /PATH/TO/SSH/KEY',
81
+ 'Specify alternate SSH key',
82
+ '(default: ~/.ssh/id_rsa)' do |key|
83
+ @cmd_options[:keyfile] = key
84
+ end
85
+
86
+ opts.on '--timeout TIMEOUT',
87
+ '(vCloud only) Specify a provisioning timeout (in seconds)',
88
+ '(default: 300)' do |value|
89
+ @cmd_options[:timeout] = value
90
+ end
91
+
92
+ opts.on '-i URI', '--install URI',
93
+ 'Install a project repo/app on the SUTs',
94
+ 'Provide full git URI or use short form KEYWORD/name',
95
+ 'supported keywords: PUPPET, FACTER, HIERA, HIERA-PUPPET' do |value|
96
+ @cmd_options[:install] = value
97
+ end
98
+
99
+ opts.on('-m', '--modules URI', 'Select puppet module git install URI') do |value|
100
+ @cmd_options[:modules] = value
101
+ end
102
+
103
+ opts.on '-q', '--[no-]quiet',
104
+ 'Do not log output to STDOUT',
105
+ '(default: false)' do |bool|
106
+ @cmd_options[:quiet] = bool
107
+ end
108
+
109
+ opts.on '-x', '--[no-]xml',
110
+ 'Emit JUnit XML reports on tests',
111
+ '(default: false)' do |bool|
112
+ @cmd_options[:xml] = bool
113
+ end
114
+
115
+ opts.on '--[no-]color',
116
+ 'Do not display color in log output',
117
+ '(default: true)' do |bool|
118
+ @cmd_options[:color] = bool
119
+ end
120
+
121
+ opts.on '--[no-]debug',
122
+ 'Enable full debugging',
123
+ '(default: false)' do |bool|
124
+ @cmd_options[:debug] = bool
125
+ end
126
+
127
+ opts.on '-d', '--[no-]dry-run',
128
+ 'Report what would happen on targets',
129
+ '(default: false)' do |bool|
130
+ @cmd_options[:dry_run] = bool
131
+ $dry_run = bool
132
+ end
133
+
134
+ opts.on '--fail-mode [MODE]',
135
+ 'How should the harness react to errors/failures',
136
+ 'Possible values:',
137
+ 'fast (skip all subsequent tests, cleanup, exit)',
138
+ 'stop (skip all subsequent tests, do no cleanup, exit immediately)' do |mode|
139
+ @cmd_options[:fail_mode] = mode
140
+ end
141
+
142
+ opts.on '--[no-]ntp',
143
+ 'Sync time on SUTs before testing',
144
+ '(default: false)' do |bool|
145
+ @cmd_options[:timesync] = bool
146
+ end
147
+
148
+ opts.on '--repo-proxy',
149
+ 'Proxy packaging repositories on ubuntu, debian and solaris-11',
150
+ '(default: false)' do
151
+ @cmd_options[:repo_proxy] = true
152
+ end
153
+
154
+ opts.on '--add-el-extras',
155
+ 'Add Extra Packages for Enterprise Linux (EPEL) repository to el-* hosts',
156
+ '(default: false)' do
157
+ @cmd_options[:add_el_extras] = true
158
+ end
159
+
160
+ opts.on '-c', '--config FILE',
161
+ 'DEPRECATED use --hosts' do |file|
162
+ @cmd_options[:hosts_file] = file
163
+ end
164
+
165
+ opts.on('--help', 'Display this screen' ) do
166
+ @cmd_options[:help] = true
167
+ end
168
+ end
169
+
170
+ end
171
+
172
+ # Parse an array of arguments into a Hash of options
173
+ # @param [Array] args The array of arguments to consume
174
+ #
175
+ # @example
176
+ # args = ['--option', 'value', '--option2', 'value2', '--switch']
177
+ # parser = CommandLineParser.new
178
+ # parser.parse!(args) == {:option => 'value, :options2 => value, :switch => true}
179
+ #
180
+ # @return [Hash] Return the Hash of options
181
+ def parse!( args = ARGV )
182
+ @optparse.parse!(args)
183
+ @cmd_options
184
+ end
185
+
186
+ # Generate a string representing the supported arguments
187
+ #
188
+ # @example
189
+ # parser = CommandLineParser.new
190
+ # parser.usage = "Options: ..."
191
+ #
192
+ # @return [String] Return a string representing the available arguments
193
+ def usage
194
+ @optparse.help
195
+ end
196
+
197
+ end
198
+ end
199
+ end