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 =
if RUBY_VERSION > '1.8.7'; then Psych::SyntaxError; else ArgumentError; end
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.
-
#split_arg(arg) ⇒ Array
Normalizes argument into an Array.
-
#usage ⇒ String
Returns a description of Beaker’s supported arguments.
Constructor Details
#initialize ⇒ Parser
Constructor for Parser
124 125 126 |
# File 'lib/beaker/options/parser.rb', line 124 def initialize @command_line_parser = Beaker::Options::CommandLineParser.new end |
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
183 184 185 186 187 188 189 190 191 192 |
# File 'lib/beaker/options/parser.rb', line 183 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
- if using docker hypervisor are using RUBY 1.9+
- 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'
210 211 212 213 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 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 |
# File 'lib/beaker/options/parser.rb', line 210 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)/ parser_error "--type must be one of pe, git, or foss, 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|never/ parser_error "--preserve_hosts must be one of always, onfail 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 #if using docker need ruby 1.9+ if hypervisors.include?('docker') if RUBY_VERSION < '1.9' parser_error "Cannot use the 'docker' hypervisor on Ruby < 1.9 (using #{RUBY_VERSION})" 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 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
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
# File 'lib/beaker/options/parser.rb', line 141 def parse_args(args = ARGV) # NOTE on argument precedence: # Will use env, then hosts/config file, then command line, then file options @options = Beaker::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 = Beaker::Options::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 |
#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 |