Class: Puppet::Util::PTomulik::Packagex::Portsx::Options

Inherits:
Object
  • Object
show all
Includes:
Vash::Contained
Defined in:
lib/puppet/util/ptomulik/packagex/portsx/options.rb

Overview

Maintain FreeBSD ports options (normally settable with ‘make search`).

This is just a hash with simple validation and few additional methods for loading, parsing and saving ports options to a file.

### Options as a validating hash

The hash accepts Strings or Symbols as keys. When entering the hash, keys are validated against a regexp accepting only well-formed identifiers (‘/^[a-zA-Z_]w*$/`). The values must be either `true`/`false` boolean values, `:on`/`:off` symbols or `’on’‘/`’off’‘ strings. If validation fails an exception is raised. The class uses [vash](github.com/ptomulik/puppet-vash) module to enforce validation and munging, and it is vash who defines the exceptions being raised.

Keys and values are internally munged, such that all input keys get converted to symbols and input values to booleans. For example:

require 'puppet/util/ptomulik/packagex/portsx/options'
opts = Puppet::Util::PTomulik::Packagex::Portsx::Options.new
opts['FOO'] = 'off'
puts opts.inspect

would print ‘:FOO=>false`.

### Loading and saving options

Options can be loaded from FreeBSD port options files or extracted from a string. They may be further converted to a string or saved to a file. The class provides following methods for that:

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.load(files, params = {}) ⇒ Object

Read options from options files. Missing files from __files__ list are ignored by default.

Parameters:

  • files (String|Array)

    file name (or array of file names) to be scanned for ports options, the files get loaded in order specified in __files__ array; options found in later files overwrite the earlier options,

  • params (Hash) (defaults to: {})

    additional parameters to alter method behavior

Options Hash (params):

  • :all (Boolean)

    load options from all files listed in __files__ (don’t skip missing files), if a file is missing the method will fail with an exception instead of silently ignoring missing files,



135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/puppet/util/ptomulik/packagex/portsx/options.rb', line 135

def self.load(files,params={})
  files = [files] unless files.is_a?(Array)
  # concatenate all files in order ...
  contents = []
  files.each do|file|
    next if (not File.exists?(file)) and not params[:all]
    msg = "Reading port options from '#{file}'"
    respond_to?(:debug) ? debug(msg) : Puppet.debug(msg)
    contents << File.read(file)
  end
  parse(contents.join("\n"))
end

.munge_option_name(name) ⇒ Symbol

Convert valid option names to symbols

Parameters:

  • name (String|Symbol)

    input name to be munged

Returns:

  • (Symbol)

    the ‘name` converted to Symbol



71
72
73
74
# File 'lib/puppet/util/ptomulik/packagex/portsx/options.rb', line 71

def self.munge_option_name(name)
  # note, on 1.8 Symbol has no :intern method
  name.is_a?(String) ? name.intern : name
end

.munge_option_value(value) ⇒ Boolean

Convert valid option values (strings, symbols) to boolean values

Parameters:

  • value (String|Symbol|Boolean)

    input value to be munged,

Returns:

  • (Boolean)

    ‘true` if the `value` is `true`, `:on`, or `on`; otherwise `false`



82
83
84
85
86
87
# File 'lib/puppet/util/ptomulik/packagex/portsx/options.rb', line 82

def self.munge_option_value(value)
  case value
  when 'on', :on, true; true
  else; false
  end
end

.option_name?(x) ⇒ Boolean

Is x valid as option name?

Parameters:

  • x

    an input value to be checked

Returns:

  • (Boolean)

    ‘true` if `x` is a valid option name, `false` if not.



52
53
54
55
# File 'lib/puppet/util/ptomulik/packagex/portsx/options.rb', line 52

def self.option_name?(x)
  x = x.to_s if x.is_a?(Symbol)
  x.is_a?(String) and x =~ /^[a-zA-Z_]\w*$/
end

.option_value?(x) ⇒ Boolean

Is x valid as option value?

Parameters:

  • x

    an input value to be checked

Returns:

  • (Boolean)

    ‘true` if `x` is a valid option value, `false` if not



62
63
64
# File 'lib/puppet/util/ptomulik/packagex/portsx/options.rb', line 62

def self.option_value?(x)
  ['on', 'off', :on, :off, true, false].include?(x)
end

.parse(string) ⇒ Puppet::Util::PTomulik::Packagex::Portsx::Options

Parse string for options.

Parameters:

  • string (String)

    a content of options file to be scanned for options,

Returns:



119
120
121
122
# File 'lib/puppet/util/ptomulik/packagex/portsx/options.rb', line 119

def self.parse(string)
  opt_re = /^\s*OPTIONS_FILE_((?:UN)?SET)\s*\+=(\w+)\s*$/
  Options[ string.scan(opt_re).map{|pair| [pair[1], pair[0]=='SET']} ]
end

.query_pkgng(key, packages = nil, params = {}) ⇒ Hash

Query pkgng for package options.

This method executes

pkg query "#{key} %Ok %Ov" ...

to extract package options for (a list of) installed package(s). See pkg-query(8) for query formats used by ‘pkg query`.

Parameters:

  • key (String)

    determines what will be used as keys in the returned hash; example values are ‘’%n’‘ - return pkgnames in keys, `’%o’‘ return pkgorigins in keys,

  • packages (Array) (defaults to: nil)

    list of packages to be queried; if not given, query all the installed packages,

  • params (Hash) (defaults to: {})

    additional parameters to alter method’s behavior,

Options Hash (params):

  • :execpipe (Method)

    handle to a method which provides ‘execpipe` functionality, should have same interface as `Puppet::Util::Execution#execpipe`,

  • :pkg (String)

    absolute path to the ‘pkg` command,

Returns:

  • (Hash)

    a hash in form ‘’package’=>{‘OPTION’=>value,…, … }‘, what is put in keys (`’package’‘ in the above example) depends on the __key__ argument,



173
174
175
176
177
178
179
180
181
182
183
# File 'lib/puppet/util/ptomulik/packagex/portsx/options.rb', line 173

def self.query_pkgng(key,packages=nil,params={})
  options = {}
  if packages
    packages.each_slice(self::PKG_ARGS_MAX) do |slice|
      query_pkgng_1(key,slice,params) { |hash| options.merge!(hash) }
    end
  else
    query_pkgng_1(key,[],params) {|hash| options.merge!(hash) }
  end
  options
end

Instance Method Details

#generate(params) ⇒ String

Write to a string all the options in form suitable to be saved as an options file. This is symmetric to what parse does.

Parameters:

  • params (Hash)

    hash of parameters to alter method’s behavior

Options Hash (params):

  • :pkgname (String)

    package name to which the options apply, by convention it should be a pkgname of the given package.

Returns:

  • (String)

    the generated content as string.



210
211
212
213
214
215
216
217
218
219
220
221
# File 'lib/puppet/util/ptomulik/packagex/portsx/options.rb', line 210

def generate(params)
  content  = "# This file is auto-generated by puppet\n"
  if params[:pkgname]
    content += "# Options for #{params[:pkgname]}\n"
    content += "_OPTIONS_READ=#{params[:pkgname]}\n"
  end
  keys.sort.each do |k|
    v = self[k]
    content += "OPTIONS_FILE_#{v ? '':'UN'}SET+=#{k}\n"
  end
  content
end

#save(file, params = {}) ⇒ Object

Note:

by default we do not allow to create directories recursivelly; we assume, that ‘/var/db/ports’ already exists and user saves its options to ‘/var/db/ports/my_port/options’;

Save package options to options file.

Parameters:

  • file (String)

    path to options’ file.

  • params (Hash) (defaults to: {})

    additional parameters to function

Options Hash (params):

  • :pkgname (String)

    package name to which the options apply, by convention it should be a pkgname of the given package,

  • :mkdir_p (Boolean)

    create directories recursively if they don’t exist; if ‘false`, only last level subdirectory is allowed to be created.



237
238
239
240
241
242
243
244
245
246
247
248
249
# File 'lib/puppet/util/ptomulik/packagex/portsx/options.rb', line 237

def save(file,params={})
  dir = File.dirname(file)
  if not File.exists?(dir)
    msg = "Creating directory #{dir}"
    respond_to?(:debug) ? debug(msg) : Puppet.debug(msg)
    params[:mkdir_p] ?  FileUtils.mkdir_p(dir) : Dir.mkdir(dir)
  end
  msg = params[:pkgname] ?
    "Saving options for '#{params[:pkgname]}' port to file '#{file}'" :
    "Saving port options to file '#{file}'"
  respond_to?(:debug) ? debug(msg) : Puppet.debug(msg)
  File.write(file,generate(params))
end

#vash_key_name(*args) ⇒ Object

Used by Vash as a key name.



102
# File 'lib/puppet/util/ptomulik/packagex/portsx/options.rb', line 102

def vash_key_name(*args);   'option name';                       end

#vash_munge_key(key) ⇒ Object

Required by Vash to have key munging in place.



98
# File 'lib/puppet/util/ptomulik/packagex/portsx/options.rb', line 98

def vash_munge_key(key);    self.class.munge_option_name(key);   end

#vash_munge_value(val) ⇒ Object

Required by Vash to have value munging in place.



100
# File 'lib/puppet/util/ptomulik/packagex/portsx/options.rb', line 100

def vash_munge_value(val);  self.class.munge_option_value(val);  end

#vash_valid_key?(x) ⇒ Boolean

Required by Vash to have key validation in place.

Returns:

  • (Boolean)


94
# File 'lib/puppet/util/ptomulik/packagex/portsx/options.rb', line 94

def vash_valid_key?(x);     self.class.option_name?(x);          end

#vash_valid_value?(x) ⇒ Boolean

Required by Vash to have value validation in place.

Returns:

  • (Boolean)


96
# File 'lib/puppet/util/ptomulik/packagex/portsx/options.rb', line 96

def vash_valid_value?(x);   self.class.option_value?(x);         end

#vash_value_exception(val, *args) ⇒ Object

Used by Vash as to generate exceptions for invalid option values.



104
105
106
107
108
109
110
# File 'lib/puppet/util/ptomulik/packagex/portsx/options.rb', line 104

def vash_value_exception(val,*args)
  name = vash_value_name(val,*args)
  msg  = "invalid value #{val.inspect}"
  msg += " at position  #{args[0].inspect}" unless args[0].nil?
  msg += " for option #{args[1].to_s}" unless args.length < 2
  [Puppet::Util::PTomulik::Vash::InvalidValueError, msg]
end