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 []
%i[helper load_path tests pre_suite post_suite install pre_cleanup modules]
- RB_FILE_OPTS =
These options expand out into an array of .rb files
%i[tests pre_suite post_suite pre_cleanup]
- PARSE_ERROR =
Psych::SyntaxError
Instance Attribute Summary collapse
-
#attribution ⇒ Object
readonly
Returns the value of attribute attribution.
-
#options ⇒ Object
The OptionsHash of all parsed options.
Instance Method Summary collapse
-
#check_hypervisor_config(visor) ⇒ nil
Validate the config file for visor exists.
-
#file_list(paths) ⇒ Array
Generates a list of files based upon a given path or list of paths.
-
#get_hypervisors(hosts) ⇒ Array
Get a unique list of hypervisors from list of host.
-
#get_roles(hosts) ⇒ Array
Get an array containing lists of roles by parsing each host in hosts.
-
#initialize ⇒ Parser
constructor
Constructor for Parser.
-
#normalize_args ⇒ Object
Validate all merged options values for correctness.
-
#normalize_test_tags! ⇒ Object
Normalize include and exclude tags.
-
#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.
-
#parse_hosts_options ⇒ Hash
Parse hosts options from host files into a host options hash.
-
#repo ⇒ String
Returns the git repository used for git installations.
-
#resolve_symlinks! ⇒ Object
resolves all file symlinks that require it.
-
#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.
-
#tag_sources(options_hash, source) ⇒ Hash
Update the @attribution hash with the source of each key in the options_hash.
-
#update_option(key, value, source) ⇒ Object
Update the @option hash with a value and the @attribution hash with a source.
-
#usage ⇒ String
Returns a description of Beaker’s supported arguments.
Constructor Details
#initialize ⇒ Parser
Constructor for Parser
165 166 167 168 169 170 |
# File 'lib/beaker/options/parser.rb', line 165 def initialize @command_line_parser = Beaker::Options::CommandLineParser.new @presets = Beaker::Options::Presets.new @validator = Beaker::Options::Validator.new @attribution = Beaker::Options::OptionsHash.new end |
Instance Attribute Details
#attribution ⇒ Object (readonly)
Returns the value of attribute attribution.
18 19 20 |
# File 'lib/beaker/options/parser.rb', line 18 def attribution @attribution end |
#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_hypervisor_config(visor) ⇒ nil
Validate the config file for visor exists.
418 419 420 421 422 423 424 |
# File 'lib/beaker/options/parser.rb', line 418 def check_hypervisor_config(visor) @validator.check_yaml_file(@options[:ec2_yaml], "required by #{visor}") if ['blimpy'].include?(visor) return unless %w(aix solaris vcloud).include?(visor) @validator.check_yaml_file(@options[:dot_fog], "required by #{visor}") 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.
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/beaker/options/parser.rb', line 62 def file_list(paths) files = [] if !paths.empty? paths.each do |root| @validator.validate_path(root) path_files = [] if File.file?(root) path_files << root elsif File.directory?(root) # expand and explore path_files = Dir.glob(File.join(root, '**/*.rb')) .select { |f| File.file?(f) } .sort_by { |file| [file.count('/'), file] } end @validator.validate_files(path_files, root) files += path_files end end @validator.validate_files(files, paths.to_s) files end |
#get_hypervisors(hosts) ⇒ Array
Get a unique list of hypervisors from list of host.
407 408 409 410 411 |
# File 'lib/beaker/options/parser.rb', line 407 def get_hypervisors(hosts) hypervisors = [] hosts.each_key { |name| hypervisors << hosts[name][:hypervisor].to_s } hypervisors.uniq end |
#get_roles(hosts) ⇒ Array
Get an array containing lists of roles by parsing each host in hosts.
395 396 397 398 399 400 401 |
# File 'lib/beaker/options/parser.rb', line 395 def get_roles(hosts) roles = [] hosts.each_key do |name| roles << hosts[name][:roles] end roles 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
- --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
- sets the default host based upon machine definitions
- if an ssh user has been defined make it the host user
326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 |
# File 'lib/beaker/options/parser.rb', line 326 def normalize_args @options['HOSTS'].each_key do |name| @validator.validate_platform(@options['HOSTS'][name], name) @options['HOSTS'][name]['platform'] = Platform.new(@options['HOSTS'][name]['platform']) end # use the keyfile if present @options[:ssh][:keys] = [@options[:keyfile]] if @options.has_key?(:keyfile) # 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) update_option(opt, split_arg(@options[opt]), 'runtime') update_option(opt, file_list(@options[opt]), 'runtime') if RB_FILE_OPTS.include?(opt) && (not @options[opt] == []) update_option(:install, parse_git_repos(@options[:install]), 'runtime') if opt == :install else update_option(opt, [], 'runtime') end end @validator.validate_fail_mode(@options[:fail_mode]) @validator.validate_preserve_hosts(@options[:preserve_hosts]) # check for config files necessary for different hypervisors hypervisors = get_hypervisors(@options[:HOSTS]) hypervisors.each do |visor| check_hypervisor_config(visor) end # check that roles of hosts make sense # - must be one and only one master master = 0 roles = get_roles(@options[:HOSTS]) roles.each do |role_array| master += 1 if role_array.include?('master') @validator.validate_frictionless_roles(role_array) end @validator.validate_master_count(master) # check that windows boxes are only agents (solaris can be a master in foss cases) @options[:HOSTS].each_key do |name| host = @options[:HOSTS][name] test_host_roles(name, host) if host[:platform].include?('windows') # check to see if a custom user account has been provided, if so use it host[:user] = host[:ssh][:user] if host[:ssh] && host[:ssh][:user] # merge host tags for this host with the global/preset host tags host[:host_tags] = @options[:host_tags].merge(host[:host_tags] || {}) end @validator.( @options[:test_tag_and], @options[:test_tag_or], @options[:test_tag_exclude], ) resolve_symlinks! # set the default role set_default_host!(@options[:HOSTS]) end |
#normalize_test_tags! ⇒ Object
refer to DSL::TestTagging for test tagging implementation
Normalize include and exclude tags. This modifies @options.
430 431 432 433 434 435 436 437 438 439 440 |
# File 'lib/beaker/options/parser.rb', line 430 def @options[:test_tag_and] ||= '' @options[:test_tag_or] ||= '' @options[:test_tag_exclude] ||= '' @options[:test_tag_and] = @options[:test_tag_and].split(',') if @options[:test_tag_and].respond_to?(:split) @options[:test_tag_or] = @options[:test_tag_or].split(',') if @options[:test_tag_or].respond_to?(:split) @options[:test_tag_exclude] = @options[:test_tag_exclude].split(',') if @options[:test_tag_exclude].respond_to?(:split) @options[:test_tag_and].map!(&:downcase) @options[:test_tag_or].map!(&:downcase) @options[:test_tag_exclude].map!(&:downcase) 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. ARGV or provided arguments array
3. the 'CONFIG' section of the hosts file
4. options file values
5. subcommand options, if executing beaker subcommands
6. subcommand options from $HOME/.beaker/subcommand_options.yaml
7. project values in .beaker.yml
8. default or preset values are given the lowest priority
214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 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 |
# File 'lib/beaker/options/parser.rb', line 214 def parse_args(args = ARGV) @options = @presets.presets @attribution = @attribution.merge(tag_sources(@presets.presets, "preset")) = @command_line_parser.parse(args) [:command_line] = ([$0] + args).join(' ') @attribution = @attribution.merge(tag_sources(, "flag")) # Merge options in reverse precedence order. First project options, # then global options from $HOME/.beaker/subcommand_options.yaml, # then subcommand options in the project. = Beaker::Subcommands::SubcommandUtil::SUBCOMMAND_OPTIONS { "project" => ".beaker.yml", "homedir" => "#{ENV.fetch('HOME', nil)}/#{}", "subcommand" => , }.each_pair do |src, path| opts = if src == "project" Beaker::Options::SubcommandOptionsParser.(path) else Beaker::Options::SubcommandOptionsParser.(args, path) end @attribution = @attribution.merge(tag_sources(opts, src)) @options.merge!(opts) end = Beaker::Options::OptionsFileParser.([:options_file] || [:options_file]) @attribution = @attribution.merge(tag_sources(, "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() if not @options[:help] and not @options[:beaker_version_print] = # merge in host file vars # overwrite options (default, file options, command line) with host file options @options = @options.merge() @attribution = @attribution.merge(tag_sources(, "host_file")) # re-merge the command line options # overwrite options (default, file options, hosts file ) with command line arguments @options = @options.merge() @attribution = @attribution.merge(tag_sources(, "cmd")) # 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) @attribution = @attribution.merge(tag_sources(env_vars, "env")) 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
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/beaker/options/parser.rb', line 111 def parse_git_repos(git_opts) git_opts.map! do |opt| case opt when /^PUPPET\// opt = "#{repo}/puppet.git##{opt.split('/', 2)[1]}" when /^FACTER\// opt = "#{repo}/facter.git##{opt.split('/', 2)[1]}" when /^HIERA\// opt = "#{repo}/hiera.git##{opt.split('/', 2)[1]}" when /^HIERA-PUPPET\// opt = "#{repo}/hiera-puppet.git##{opt.split('/', 2)[1]}" end opt end git_opts end |
#parse_hosts_options ⇒ Hash
Parse hosts options from host files into a host options hash. Falls back to trying as a beaker-hostgenerator string if reading the hosts file doesn’t work
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 |
# File 'lib/beaker/options/parser.rb', line 283 def if @options[:hosts_file].nil? || File.exist?(@options[:hosts_file]) # read the hosts file that contains the node configuration and hypervisor info return Beaker::Options::HostsFileParser.parse_hosts_file(@options[:hosts_file]) end = "\nHosts file '#{@options[:hosts_file]}' does not exist." << "\nTrying as beaker-hostgenerator input.\n\n" $stdout.puts require 'beaker-hostgenerator' = [@options[:hosts_file]] += ['--hypervisor', ENV['BEAKER_HYPERVISOR']] if ENV['BEAKER_HYPERVISOR'] hosts_file_content = begin bhg_cli = BeakerHostGenerator::CLI.new() bhg_cli.execute rescue BeakerHostGenerator::Exceptions::Error => e = "\nbeaker-hostgenerator was not able to use this value as input." << "\nExiting with an Error.\n\n" $stderr.puts raise e end @options[:hosts_file_generated] = true Beaker::Options::HostsFileParser.parse_hosts_string(hosts_file_content) end |
#repo ⇒ String
Returns the git repository used for git installations
22 23 24 |
# File 'lib/beaker/options/parser.rb', line 22 def repo GITREPO end |
#resolve_symlinks! ⇒ Object
doing it here allows us to not need duplicate logic, which we would need if we were doing it in the parser (–hosts & –config)
resolves all file symlinks that require it. This modifies @options.
93 94 95 96 97 |
# File 'lib/beaker/options/parser.rb', line 93 def resolve_symlinks! return unless @options[:hosts_file] && !@options[:hosts_file_generated] @options[:hosts_file] = File.realpath(@options[:hosts_file]) 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.
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 159 160 161 |
# File 'lib/beaker/options/parser.rb', line 133 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 # default_set? will throw an error if length > 1 # and return false if no default is set. return if @validator.default_set?(default) # 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 return unless default_host_name hosts[default_host_name][:roles] << 'default' 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.
42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/beaker/options/parser.rb', line 42 def split_arg arg arry = [] if arg.is_a?(Array) arry += arg elsif arg.include?(',') arry += arg.split(',') else arry << arg end arry end |
#tag_sources(options_hash, source) ⇒ Hash
Update the @attribution hash with the source of each key in the options_hash
177 178 179 180 181 182 183 184 185 186 187 |
# File 'lib/beaker/options/parser.rb', line 177 def tag_sources(, source) hash = Beaker::Options::OptionsHash.new .each do |key, value| hash[key] = if value.is_a?(Hash) tag_sources(value, source) else source end end hash end |
#update_option(key, value, source) ⇒ Object
Update the @option hash with a value and the @attribution hash with a source
194 195 196 197 |
# File 'lib/beaker/options/parser.rb', line 194 def update_option(key, value, source) @options[key] = value @attribution[key] = source end |
#usage ⇒ String
Returns a description of Beaker’s supported arguments
28 29 30 |
# File 'lib/beaker/options/parser.rb', line 28 def usage @command_line_parser.usage end |