Module: Puppet::Pops::Binder::BindingsFactory

Defined in:
lib/puppet/pops/binder/bindings_factory.rb

Overview

A helper class that makes it easier to construct a Bindings model.

The Bindings Model


The BindingsModel (defined in Bindings is a model that is intended to be generally free from Ruby concerns. This means that it is possible for system integrators to create and serialize such models using other technologies than Ruby. This manifests itself in the model in that producers are described using instances of a ‘ProducerDescriptor` rather than describing Ruby classes directly. This is also true of the type system where type is expressed using the Types model to describe all types.

This class, the ‘BindingsFactory` is a concrete Ruby API for constructing instances of classes in the model.

Named Bindings


The typical usage of the factory is to call BindingsFactory.named_bindings which creates a container of bindings wrapped in a *build object* equipped with convenience methods to define the details of the just created named bindings. The returned builder is an instance of BindingsContainerBuilder.

Binding


A Binding binds a type/name key to a producer of a value. A binding is conveniently created by calling ‘bind` on a `BindingsContainerBuilder`. The call to bind, produces a binding wrapped in a build object equipped with convenience methods to define the details of the just created binding. The returned builder is an instance of BindingsBuilder.

Multibinding


A multibinding works like a binding, but it requires an additional ID. It also places constraints on the type of the binding; it must be a collection type (Hash or Array).

Constructing and Contributing Bindings from Ruby


The bindings system is used by referencing bindings symbolically; these are then specified in a Ruby file which is autoloaded by Puppet. The entry point for user code that creates bindings is described in Bindings. That class makes use of a BindingsFactory, and the builder objects to make it easy to construct bindings.

It is intended that a user defining bindings in Ruby should be able to use the builder object methods for the majority of tasks. If something advanced is wanted, use of one of the helper class methods on the BuildingsFactory, and/or the TypeCalculator will be required to create and configure objects that are not handled by the methods in the builder objects.

Chaining of calls


Since all the build methods return the build object it is easy to stack on additional calls. The intention is to do this in an order that is readable from left to right: ‘bind.string.name(’thename’).to(42)‘, but there is nothing preventing making the calls in some other order e.g. `bind.to(42).name(’thename’).string`, the second is quite unreadable but produces the same result.

For sake of human readability, the method ‘name` is alsp available as `named`, with the intention that it is used after a type, e.g. `bind.integer.named(’the meaning of life’).to(42)‘

Methods taking blocks


Several methods take an optional block. The block evaluates with the builder object as ‘self`. This means that there is no need to chain the methods calls, they can instead be made in sequence - e.g.

bind do
  integer
  named 'the meaning of life'
  to 42
end

or mix the two styles

bind do
  integer.named 'the meaning of life'
  to 42
end

Unwrapping the result


The result from all methods is a builder object. Call the method ‘model` to unwrap the constructed bindings model object.

bindings = BindingsFactory.named_bindings('my named bindings') do
  # bind things
end.model

Examples:

Create a NamedBinding with content

result = Puppet::Pops::Binder::BindingsFactory.named_bindings("mymodule::mybindings") do
  bind.name("foo").to(42)
  bind.string.name("site url").to("http://www.example.com")
end
result.model()

Defined Under Namespace

Classes: AbstractBuilder, BindingsBuilder, BindingsContainerBuilder, MultibindingsBuilder

Constant Summary collapse

T =

Alias for the TypeFactory. This is also available as the method ‘type_factory`.

Puppet::Pops::Types::TypeFactory

Class Method Summary collapse

Class Method Details

.contributed_bindings(name, named_bindings) ⇒ Object

Produces a ContributedBindings. A ContributedBindings is used by bindings providers to return a set of named bindings.

Parameters:



603
604
605
606
607
608
609
# File 'lib/puppet/pops/binder/bindings_factory.rb', line 603

def self.contributed_bindings(name, named_bindings)
  cb = Puppet::Pops::Binder::Bindings::ContributedBindings.new()
  cb.name = name
  named_bindings = [named_bindings] unless named_bindings.is_a?(Array)
  named_bindings.each {|b| cb.addBindings(b) }
  cb
end

.evaluating_producer(expression) ⇒ Puppet::Pops::Binder::Bindings::ProducerDescriptor

Creates an evaluating producer that evaluates a puppet expression. A puppet expression is most conveniently created by using the EvaluatingParser as it performs all set up and validation of the parsed source. Two convenience methods are used to parse an expression, or parse a ruby string as a puppet string. See methods puppet_expression, puppet_string and parser for more information.

Examples:

producing a puppet expression

expr = puppet_string("Interpolated $fqdn", __FILE__)

Parameters:

Returns:



752
753
754
755
756
# File 'lib/puppet/pops/binder/bindings_factory.rb', line 752

def self.evaluating_producer(expression)
  p = Puppet::Pops::Binder::Bindings::EvaluatingProducerDescriptor.new()
  p.expression = expression
  p
end

.first_found_producer(*producers) ⇒ Puppet::Pops::Binder::Bindings::ProducerDescriptor

Creates a first-found producer that looks up from a given series of keys. The first found looked up value will be produced.

Parameters:

Returns:



734
735
736
737
738
# File 'lib/puppet/pops/binder/bindings_factory.rb', line 734

def self.first_found_producer(*producers)
  p = Puppet::Pops::Binder::Bindings::FirstFoundProducerDescriptor.new()
  producers.each {|p2| p.addProducers(p2) }
  p
end

.hash_lookup_producer(type, name, key) ⇒ Puppet::Pops::Binder::Bindings::ProducerDescriptor

Creates a Hash lookup producer that looks up a hash value, and then a key in the hash.

Parameters:

  • type (Puppet::Pops::Types::PAnyType)

    the type to lookup (i.e. a Hash of some key/value type).

  • name (String)

    the name to lookup

  • key (Object)

    the key to lookup in the looked up hash (type should comply with given key type).

Returns:



721
722
723
724
725
726
727
# File 'lib/puppet/pops/binder/bindings_factory.rb', line 721

def self.hash_lookup_producer(type, name, key)
  p = Puppet::Pops::Binder::Bindings::HashLookupProducerDescriptor.new()
  p.type = type
  p.name = name
  p.key = key
  p
end

.instance_producer(class_name, *args) ⇒ Puppet::Pops::Binder::Bindings::ProducerDescriptor

Creates an instance producer An instance producer creates a new instance of a class. If the class implements the class method ‘inject` this method is called instead of `new` to allow further lookups to take place. This is referred to as *assisted inject*. If the class method `inject` is missing, the regular `new` method is called.

Parameters:

  • class_name (String)

    the name of the class

  • args (Object)

    arguments to the class’ ‘new` method.

Returns:



694
695
696
697
698
699
# File 'lib/puppet/pops/binder/bindings_factory.rb', line 694

def self.instance_producer(class_name, *args)
  p = Puppet::Pops::Binder::Bindings::InstanceProducerDescriptor.new()
  p.class_name = class_name
  args.each {|a| p.addArguments(a) }
  p
end

.layered_bindings(*named_layers) ⇒ Puppet::Pops::Binder::Bindings::LayeredBindings

Create a LayeredBindings. This is used by the bindings system to create a model of all given layers.

Parameters:

Returns:



774
775
776
777
778
# File 'lib/puppet/pops/binder/bindings_factory.rb', line 774

def self.layered_bindings(*named_layers)
  result = Puppet::Pops::Binder::Bindings::LayeredBindings.new()
  named_layers.each {|b| result.addLayers(b) }
  result
end

.literal_producer(value) ⇒ Puppet::Pops::Binder::Bindings::ProducerDescriptor

Creates a literal/constant producer

Parameters:

  • value (Object)

    the value to produce

Returns:



655
656
657
658
659
# File 'lib/puppet/pops/binder/bindings_factory.rb', line 655

def self.literal_producer(value)
  producer = Puppet::Pops::Binder::Bindings::ConstantProducerDescriptor.new()
  producer.value = value
  producer
end

.lookup_producer(type, name) ⇒ Puppet::Pops::Binder::Bindings::ProducerDescriptor

Creates a Producer that looks up a value.

Parameters:

Returns:



706
707
708
709
710
711
# File 'lib/puppet/pops/binder/bindings_factory.rb', line 706

def self.lookup_producer(type, name)
  p = Puppet::Pops::Binder::Bindings::LookupProducerDescriptor.new()
  p.type = type
  p.name = name
  p
end

.named_bindings(name, &block) ⇒ Object

Creates a named binding container, the top bindings model object. A NamedBindings is typically produced by a bindings provider.

The created container is wrapped in a BindingsContainerBuilder for further detailing. Unwrap the built result when done.



618
619
620
621
622
623
624
# File 'lib/puppet/pops/binder/bindings_factory.rb', line 618

def self.named_bindings(name, &block)
  binding = Puppet::Pops::Binder::Bindings::NamedBindings.new()
  binding.name = name
  builder = BindingsContainerBuilder.new(binding)
  builder.instance_eval(&block) if block_given?
  builder
end

.named_layer(name, *bindings) ⇒ Object

Creates a NamedLayer. This is used by the bindings system to create a model of the layers.



762
763
764
765
766
767
# File 'lib/puppet/pops/binder/bindings_factory.rb', line 762

def self.named_layer(name, *bindings)
  result = Puppet::Pops::Binder::Bindings::NamedLayer.new()
  result.name = name
  bindings.each { |b| result.addBindings(b) }
  result
end

.non_caching_producer(producer) ⇒ Puppet::Pops::Binder::Bindings::ProducerDescriptor

Creates a non caching producer

Parameters:

  • producer (Puppet::Pops::Binder::Bindings::Producer)

    the producer to make non caching

Returns:



666
667
668
669
670
# File 'lib/puppet/pops/binder/bindings_factory.rb', line 666

def self.non_caching_producer(producer)
  p = Puppet::Pops::Binder::Bindings::NonCachingProducerDescriptor.new()
  p.producer = producer
  p
end

.parserPuppet::Pops::Parser::EvaluatingParser

Returns a parser for puppet expressions.

Returns:



781
782
783
# File 'lib/puppet/pops/binder/bindings_factory.rb', line 781

def self.parser
  @parser ||= Puppet::Pops::Parser::EvaluatingParser.new()
end

.producer_producer(producer) ⇒ Puppet::Pops::Binder::Bindings::ProducerDescriptor

Creates a producer producer

Parameters:

  • producer (Puppet::Pops::Binder::Bindings::Producer)

    a producer producing a Producer.

Returns:



677
678
679
680
681
# File 'lib/puppet/pops/binder/bindings_factory.rb', line 677

def self.producer_producer(producer)
  p = Puppet::Pops::Binder::Bindings::ProducerProducerDescriptor.new()
  p.producer = producer
  p
end

.puppet_expression(string, source_file) ⇒ Puppet::Pops::Model::Expression

Parses and produces a puppet expression from the given string.

Parameters:

  • string (String)

    puppet source e.g. “1 + 2”

  • source_file (String)

    the source location, typically ‘__File__`

Returns:



791
792
793
# File 'lib/puppet/pops/binder/bindings_factory.rb', line 791

def self.puppet_expression(string, source_file)
  parser.parse_string(string, source_file).current
end

.puppet_string(string, source_file) ⇒ Puppet::Pops::Model::Expression

Parses and produces a puppet string expression from the given string. The string will automatically be quoted and special characters escaped. As an example if given the (ruby) string “HinMary” it is transformed to the puppet string (illustrated with a ruby string) “"Hi\nMary”” before being parsed.

Parameters:

  • string (String)

    puppet source e.g. “On node ${fqdn}”

  • source_file (String)

    the source location, typically ‘__File__`

Returns:



806
807
808
# File 'lib/puppet/pops/binder/bindings_factory.rb', line 806

def self.puppet_string(string, source_file)
  parser.parse_string(parser.quote(string), source_file).current
end

.safe_named_bindings(name, scope, &block) ⇒ 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.

This variant of named_bindings evaluates the given block as a method on an anonymous class, thus, if the block defines methods or do something with the class itself, this does not pollute the base class (BindingsContainerBuilder).



631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
# File 'lib/puppet/pops/binder/bindings_factory.rb', line 631

def self.safe_named_bindings(name, scope, &block)
  binding = Puppet::Pops::Binder::Bindings::NamedBindings.new()
  binding.name = name
  anon = Class.new(BindingsContainerBuilder) do
    def initialize(b)
      super b
    end
  end
  anon.send(:define_method, :_produce, block)
  builder = anon.new(binding)
  case block.arity
  when 0
    builder._produce()
  when 1
    builder._produce(scope)
  end
  builder
end