Module: Puppet::Macros

Extended by:
DefaultEnvironment, ToLambda, Validation
Defined in:
lib/puppet/macros.rb,
lib/puppet/macros.rb

Overview

This object keeps track of macros defined within a single puppet environment. Existing hashes (macros for existing environments) may be retrieved with Macros.macros method.

Constant Summary collapse

MACRO_NAME_RE =

Regular expession used to validate macro names.

/^[a-z_][a-z0-9_]*(?:::[a-z_][a-z0-9_]*)*$/

Class Method Summary collapse

Methods included from ToLambda

to_lambda

Methods included from Validation

check_macro_arity, macro_arities, macro_arities_by_arity, macro_arities_by_parameters, validate_name

Methods included from DefaultEnvironment

default_environment

Class Method Details

.autoloaderObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Accessor for singleton autoloader


231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
# File 'lib/puppet/macros.rb', line 231

def autoloader
  unless @autoloader
    # Patched autoloader whith 'loadall' searching recursivelly
    @autoloader = Puppet::Util::Autoload.new(
      self, "puppet/macros", :wrap => false
    )
    class << @autoloader
      def loadall
        self.class.loadall(File.join(@path,"**"))
      end
      def files_to_load
        self.class.files_to_load(File.join(@path,"**"))
      end
      unless instance_methods.include?(:expand) or instance_methods.include?('expand')
        # Fix for puppet 2.7, which does not have the Autoload.expand
        # method
        def expand(name)
          ::File.join(@path, name.to_s)
        end
      end
    end
  end
  @autoloader
end

.call_macro(scope, name, args, options = {}, env = default_environment) ⇒ Object

Call a macro.

Parameters:

  • scope (Puppet::Parser::Scope)

    scope of the calling function

  • name (String)

    name of the macro to be invoked

  • args (Array)

    arguments to be provided to teh macro

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

    additional options

  • env (Puppet::Node::Environment) (defaults to: default_environment)

    environment

Options Hash (options):

  • :a_err (Class)

    an exception to be raised when argument validation fails, defaults to ArgumentError

  • :l_err (Class)

    an exception to be raised when macro lookup fails, defaults to Puppet::Error

Returns:

  • the value of macro (result of evaluation)


337
338
339
340
341
342
# File 'lib/puppet/macros.rb', line 337

def call_macro(scope, name, args, options = {}, env = default_environment)
  validate_name(name, options[:a_err] || ArgumentError)
  macro = get_macro(name, env, options[:l_err] || Puppet::Error)
  check_macro_arity(macro, args, options[:a_err] || ArgumentError)
  scope.instance_exec(*args,&macro)
end

.call_macro_from_func(scope, func_name, func_args, n = 0, env = default_environment) ⇒ Object

Call a macro from parser function.

This method is dedicated to be called from a parser function. It's used by determine and invoke, but may be used by other custom functions as well. This method checks the arguments and in case of validation error raises Puppet::ParseError with appropriate message. If there is error in number of arguments to macro, the exception message will reflect the number of arguments to function, not the macro.

Parameters:

  • scope (Puppet::Parser::Scope)

    scope of the calling function

  • func_name (Symbol|String)

    name of the calling function

  • func_args (Array)

    arguments, as provided to calling function

  • n (Integer) (defaults to: 0)

    number of extra arguments shifted from function's argument list

  • env (Puppet::Node::Environment) (defaults to: default_environment)

    environment

Returns:

  • the value of macro (result of evaluation)


361
362
363
364
365
366
367
368
369
370
371
372
# File 'lib/puppet/macros.rb', line 361

def call_macro_from_func(scope, func_name, func_args, n = 0, env = default_environment)
  begin
    if(func_args.size == 0)
      raise Puppet::ParseError, "Wrong number of arguments (0) - missing macro name"
    end
    options = { :a_err => Puppet::ParseError, :l_err => Puppet::ParseError }
    call_macro(scope, func_args[0], func_args[1..-1], options, env)
  rescue Puppet::ParseError => err
    msg = fix_error_msg(func_name, err.message, 1+n)
    raise Puppet::ParseError, msg, err.backtrace
  end
end

.fix_error_msg(func, msg, n = 0) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Fix error messages to indicate number of arguments to parser function instead of the number of arguments to macro and prepend the function name.

Parameters:

  • func (Symbol|String)

    function name,

  • msg (String)

    original message from callee,

  • n (Integer) (defaults to: 0)

    number of arguments shifted from function's arglist,

Returns:

  • (String)

    fixed message


315
316
317
318
319
320
321
322
# File 'lib/puppet/macros.rb', line 315

def fix_error_msg(func, msg, n = 0)
  re = /^Wrong number of arguments \(([0-9]+) for (minimum |maximum )?([0-9]+)\)$/
  if m = re.match(msg)
    msg = "Wrong number of arguments (#{n+Integer(m.captures[0])} " +
      "for #{m.captures[1]}#{n+Integer(m.captures[2])})"
  end
  "#{func}(): #{msg}"
end

.get_macro(name, env = default_environment, errclass = Puppet::Error) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.


300
301
302
303
304
305
# File 'lib/puppet/macros.rb', line 300

def get_macro(name, env = default_environment, errclass = Puppet::Error)
  unless macro = self.macro(name,env)
    raise errclass, "Undefined macro #{name}"
  end
  macro
end

.load(name, env = default_environment) ⇒ Macro|nil

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Load single macro from file

Parameters:

  • name (String)

    macro name, e.g. 'foo::bar',

  • env (Puppet::Node::Environment) (defaults to: default_environment)

    puppet environment,

Returns:

  • (Macro|nil)

262
263
264
265
266
267
# File 'lib/puppet/macros.rb', line 262

def load(name, env = default_environment)
  # This block autoloads appropriate file each time a missing macro is
  # requested from hash.
  path = name.split('::').join('/')
  load_from_file(name, path, env)
end

.load_from_file(name, path, env = default_environment) ⇒ Macro|nil

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Load single file possibly containing macro definition.

Parameters:

  • name (String)

    name of the macro to be loaded

  • path (String)

    path to macro file, relative to puppet/macros and without .rb suffix,

  • env (Puppet::Node::Environment) (defaults to: default_environment)

    puppet environment,

Returns:

  • (Macro|nil)

277
278
279
280
281
282
283
284
285
286
287
288
289
# File 'lib/puppet/macros.rb', line 277

def load_from_file(name, path, env = default_environment)
  if autoloader.load(path, env)
    # the autoloaded code should add its macro to macros
    unless m = self.macro(name,env,false)
      Puppet.debug("#{autoloader.expand(path).inspect} loaded but it " +
        "didn't define macro #{name.inspect}")
    end
    m
  else
    Puppet.debug("could not autoload #{autoloader.expand(path).inspect}")
    nil
  end
end

.loadallArray

Autoload all existing macro definitions in current environment

Parameters:

  • env (Puppet::Node::Environment)

    puppet environment,

Returns:

  • (Array)

    an array of loaded files


295
296
297
# File 'lib/puppet/macros.rb', line 295

def loadall
  autoloader.loadall
end

.macro(name, env = default_environment, auto = true) ⇒ Object

Retrieve single macro from macros

Parameters:

  • name (String)

    macro name,

  • env (Puppet::Node::Environment) (defaults to: default_environment)

    puppet environment,


224
225
226
227
# File 'lib/puppet/macros.rb', line 224

def macro(name, env = default_environment, auto = true)
  root = Puppet::Node::Environment.root
  macros(env)[name] || macros(root)[name] || (auto ? load(name,env) : nil)
end

.macros(env = default_environment) ⇒ Hash

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Get a hash of registered macros.

Parameters:

  • env (Puppet::Node::Environment) (defaults to: default_environment)

    puppet environment

Returns:

  • (Hash)

    a hash with registered parser macros


215
216
217
218
# File 'lib/puppet/macros.rb', line 215

def macros(env = default_environment)
  @macros ||= {}
  @macros[env] ||= {}
end

.newmacro(name, options = {}, &block) ⇒ Object

Define new preprocessor macro.

A preprocessor macro is a callable object, which can be executed from within a puppet manifest.

Example:

Definition:

 # puppet/macros/apache/package.rb
 Puppet::Parser.Macro.newmacro 'apache::package' do
   setcode do
     case os = fact(:osfamily)
     when 'FreeBSD'
       'www/apache22'
     when 'Debian'
       'apache2'
     else
       raise Puppet::Error, "#{os} is not supported"
     end
   end
 end

Usage:

 # manifest.pp
 $package = determine('apache::package')

Parameters:

  • name (String)

    macro name

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

    additional options

  • block (Proc)

    macro definition

Options Hash (options):

  • environment (Puppet::Node::Environment)

    an environment this macro belongs to, defautls to default_environment


203
204
205
206
207
208
# File 'lib/puppet/macros.rb', line 203

def newmacro(name,options={},&block)
  env = options[:environment] || default_environment
  Puppet.debug "overwritting macro #{name}" if macro(name,env,false)
  validate_name(name)
  macros(env)[name] = to_lambda(block)
end

.valid_name?(name) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Check whether name is a valid macro name.

Parameters:

  • name

    a name to be validated

Returns:

  • (Boolean)

    true if the name is valid, or false otherwise


161
162
163
# File 'lib/puppet/macros.rb', line 161

def valid_name?(name)
  name.is_a?(String) and MACRO_NAME_RE.match(name)
end