Class: Beaker::Options::Parser
- Inherits:
-
Object
- Object
- Beaker::Options::Parser
- Defined in:
- lib/beaker/options/parser.rb
Overview
An Object that parses, merges and normalizes all supported Beaker options and arguments
Constant Summary collapse
- GITREPO =
'git://github.com/puppetlabs'
- LONG_OPTS =
These options can have the form of arg1,arg2 or [arg] or just arg, should default to []
[:helper, :load_path, :tests, :pre_suite, :post_suite, :install, :modules]
- RB_FILE_OPTS =
These options expand out into an array of .rb files
[:tests, :pre_suite, :post_suite]
- PARSE_ERROR =
Psych::SyntaxError
Instance Attribute Summary collapse
-
#options ⇒ Object
The OptionsHash of all parsed options.
Instance Method Summary collapse
-
#check_yaml_file(f, msg = "") ⇒ Object
Determine is a given file exists and is a valid YAML file.
-
#file_list(paths) ⇒ Array
Generates a list of files based upon a given path or list of paths.
-
#initialize ⇒ Parser
constructor
Constructor for Parser.
-
#normalize_args ⇒ Object
Validate all merged options values for correctness.
-
#parse_args(args = ARGV) ⇒ Object
Parses ARGV or provided arguments array, file options, hosts options and combines with environment variables and preset defaults to generate a Hash representing the Beaker options for a given test run.
-
#parse_git_repos(git_opts) ⇒ Array
Converts array of paths into array of fully qualified git repo URLS with expanded keywords.
-
#parser_error(msg = "") ⇒ Object
Raises an ArgumentError with associated message.
-
#repo ⇒ String
Returns the git repository used for git installations.
-
#set_default_host!(hosts) ⇒ Object
Add the ‘default’ role to the host determined to be the default.
-
#split_arg(arg) ⇒ Array
Normalizes argument into an Array.
-
#usage ⇒ String
Returns a description of Beaker’s supported arguments.
Constructor Details
Instance Attribute Details
#options ⇒ Object
The OptionsHash of all parsed options
17 18 19 |
# File 'lib/beaker/options/parser.rb', line 17 def @options end |
Instance Method Details
#check_yaml_file(f, msg = "") ⇒ Object
Determine is a given file exists and is a valid YAML file
222 223 224 225 226 227 228 229 230 231 |
# File 'lib/beaker/options/parser.rb', line 222 def check_yaml_file(f, msg = "") if not File.file?(f) parser_error "#{f} does not exist (#{msg})" end begin YAML.load_file(f) rescue PARSE_ERROR => e parser_error "#{f} is not a valid YAML file (#{msg})\n\t#{e}" end end |
#file_list(paths) ⇒ Array
Generates a list of files based upon a given path or list of paths.
Looks recursively for .rb files in paths.
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/beaker/options/parser.rb', line 68 def file_list(paths) files = [] if not paths.empty? paths.each do |root| if File.file?(root) files << root elsif File.directory?(root) #expand and explore discover_files = Dir.glob( File.join(root, "**/*.rb") ).select { |f| File.file?(f) } if discover_files.empty? parser_error "empty directory used as an option (#{root})!" end files += discover_files.sort_by {|file| [file.count("/"), file]} else #not a file, not a directory, not nothin' parser_error "#{root} used as a file option but is not a file or directory!" end end end if files.empty? parser_error "no .rb files found in #{paths.to_s}" end files end |
#normalize_args ⇒ Object
Validate all merged options values for correctness
Currently checks:
- each host has a valid platform
- if a keyfile is provided then use it
- paths provided to --test, --pre-suite, --post-suite provided lists of .rb files for testing
- --type is one of 'pe' or 'git'
- --fail-mode is one of 'fast', 'stop' or nil
- if using blimpy hypervisor an EC2 YAML file exists
- if using the aix, solaris, or vcloud hypervisors a .fog file exists
- that one and only one master is defined per set of hosts
- that solaris/windows/aix hosts are agent only for PE tests OR
- that windows/aix host are agent only if type is not 'pe'
- sets the default host based upon machine definitions
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 |
# File 'lib/beaker/options/parser.rb', line 249 def normalize_args @options['HOSTS'].each_key do |name| if not @options['HOSTS'][name]['platform'] parser_error "Host #{name} does not have a platform specified" else @options['HOSTS'][name]['platform'] = Platform.new(@options['HOSTS'][name]['platform']) end end #use the keyfile if present if @options.has_key?(:keyfile) @options[:ssh][:keys] = [@options[:keyfile]] end #split out arguments - these arguments can have the form of arg1,arg2 or [arg] or just arg #will end up being normalized into an array LONG_OPTS.each do |opt| if @options.has_key?(opt) @options[opt] = split_arg(@options[opt]) if RB_FILE_OPTS.include?(opt) @options[opt] = file_list(@options[opt]) end if opt == :install @options[:install] = parse_git_repos(@options[:install]) end else @options[opt] = [] end end #check for valid type if @options[:type] !~ /pe|git|foss|aio/ parser_error "--type must be one of pe, git, foss, or aio not '#{@options[:type]}'" end #check for valid fail mode if @options[:fail_mode] !~ /stop|fast|slow/ parser_error "--fail-mode must be one of fast or slow, not '#{@options[:fail_mode]}'" end #check for valid preserve_hosts option if @options[:preserve_hosts] !~ /always|onfail|onpass|never/ parser_error "--preserve_hosts must be one of always, onfail, onpass or never, not '#{@options[:preserve_hosts]}'" end #check for config files necessary for different hypervisors hypervisors = [] @options[:HOSTS].each_key do |name| hypervisors << @options[:HOSTS][name][:hypervisor].to_s end hypervisors.uniq! hypervisors.each do |visor| if ['blimpy'].include?(visor) check_yaml_file(@options[:ec2_yaml], "required by #{visor}") end if ['aix', 'solaris', 'vcloud'].include?(visor) check_yaml_file(@options[:dot_fog], "required by #{visor}") end end #check that roles of hosts make sense # - must be one and only one master roles = [] @options[:HOSTS].each_key do |name| roles << @options[:HOSTS][name][:roles] end master = 0 roles.each do |role_array| if role_array.include?('master') master += 1 end if role_array.include?('frictionless') and !(role_array & ['master', 'database', 'dashboard', 'console']).empty? parser_error "Only agent nodes may have the role 'frictionless', fix #{@options[:hosts_file]}" end end if master > 1 parser_error "Only one host/node may have the role 'master', fix #{@options[:hosts_file]}" end #check that solaris/windows/el-4 boxes are only agents @options[:HOSTS].each_key do |name| host = @options[:HOSTS][name] if (host[:platform] =~ /windows|el-4/) || (@options.is_pe? && host[:platform] =~ /solaris/) test_host_roles(name, host) end end #set the default role set_default_host!(@options[:HOSTS]) end |
#parse_args(args = ARGV) ⇒ Object
Parses ARGV or provided arguments array, file options, hosts options and combines with environment variables and preset defaults to generate a Hash representing the Beaker options for a given test run
Order of priority is as follows:
1. environment variables are given top priority
2. host file options
3. the 'CONFIG' section of the hosts file
4. ARGV or provided arguments array
5. options file values
6. default or preset values are given the lowest priority
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 |
# File 'lib/beaker/options/parser.rb', line 180 def parse_args(args = ARGV) # NOTE on argument precedence: # Will use env, then hosts/config file, then command line, then file options @options = @presets.presets = @command_line_parser.parse(args) = Beaker::Options::OptionsFileParser.([:options_file]) # merge together command line and file_options # overwrite file options with command line options = .merge() # merge command line and file options with defaults # overwrite defaults with command line and file options @options = @options.merge() @options[:command_line] = ([$0] + args).join(' ') if not @options[:help] and not @options[:version] #read the hosts file that contains the node configuration and hypervisor info = Beaker::Options::HostsFileParser.parse_hosts_file(@options[:hosts_file]) # merge in host file vars # overwrite options (default, file options, command line, env) with host file options @options = @options.merge() # merge in env vars # overwrite options (default, file options, command line, hosts file) with env env_vars = @presets.env_vars @options = @options.merge(env_vars) normalize_args end @options end |
#parse_git_repos(git_opts) ⇒ Array
Converts array of paths into array of fully qualified git repo URLS with expanded keywords
Supports the following keywords
PUPPET
FACTER
HIERA
HIERA-PUPPET
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/beaker/options/parser.rb', line 105 def parse_git_repos(git_opts) git_opts.map! { |opt| case opt when /^PUPPET\// opt = "#{GITREPO}/puppet.git##{opt.split('/', 2)[1]}" when /^FACTER\// opt = "#{GITREPO}/facter.git##{opt.split('/', 2)[1]}" when /^HIERA\// opt = "#{GITREPO}/hiera.git##{opt.split('/', 2)[1]}" when /^HIERA-PUPPET\// opt = "#{GITREPO}/hiera-puppet.git##{opt.split('/', 2)[1]}" end opt } git_opts end |
#parser_error(msg = "") ⇒ Object
Raises an ArgumentError with associated message
22 23 24 |
# File 'lib/beaker/options/parser.rb', line 22 def parser_error msg = "" raise ArgumentError, msg.to_s end |
#repo ⇒ String
Returns the git repository used for git installations
28 29 30 |
# File 'lib/beaker/options/parser.rb', line 28 def repo GITREPO end |
#set_default_host!(hosts) ⇒ Object
Add the ‘default’ role to the host determined to be the default. If a host already has the role default then do nothing. If more than a single host has the role ‘default’, raise error. Default host determined to be 1) the only host in a single host configuration, 2) the host with the role ‘master’ defined.
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
# File 'lib/beaker/options/parser.rb', line 127 def set_default_host!(hosts) default = [] master = [] default_host_name = nil #look through the hosts and find any hosts with role 'default' and any hosts with role 'master' hosts.each_key do |name| host = hosts[name] if host[:roles].include?('default') default << name elsif host[:roles].include?('master') master << name end end if not default.empty? #we already have a default set, do nothing if default.length > 1 parser_error "Only one host may have the role 'default', default roles assigned to #{default}" end else #no default set, let's make one if not master.empty? and master.length == 1 default_host_name = master[0] elsif hosts.length == 1 default_host_name = hosts.keys[0] end if default_host_name hosts[default_host_name][:roles] << 'default' end end end |
#split_arg(arg) ⇒ Array
Normalizes argument into an Array. Argument can either be converted into an array of a single value, or can become an array of multiple values by splitting arg over ‘,’. If argument is already an array that array is returned untouched.
48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/beaker/options/parser.rb', line 48 def split_arg arg arry = [] if arg.is_a?(Array) arry += arg elsif arg =~ /,/ arry += arg.split(',') else arry << arg end arry end |
#usage ⇒ String
Returns a description of Beaker’s supported arguments
34 35 36 |
# File 'lib/beaker/options/parser.rb', line 34 def usage @command_line_parser.usage end |