Module: Puppet::Macros

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

Constant Summary collapse

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

Instance Attribute Summary collapse

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

Instance Attribute Details

#environmentObject

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



148
149
150
# File 'lib/puppet/macros.rb', line 148

def environment
  @environment
end

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



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

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 respond_to?(: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)



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

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)



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

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



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

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.



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

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)


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

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)


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

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



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

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,



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

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



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

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:

```ruby
# 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:

```puppet
# 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`



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

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



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

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