Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Puppet, how can I access a variable/attribute inside a defined type?

Tags:

puppet

I would like to reference variables inside instances of defined types. For example, what can I do to reference $x and $y of foo a in bar b?

 define foo($x, $y) {
  }

  define bar($foo) {
          notify { "${::$foo::x}": } # <- how to make this reference work?
  }

  foo { 'a':
          x => 'oh bar may you reference me',
          y => 'please'
  }

  bar { 'b':
          foo     => Foo['a'],
          require => Foo['a']
  }

The reason why I would like this to work is that a foo instance may contain many values that I wouldn't like to repeat to each and every resource that might need them. Instead of passing those values again and again, thus repeating myself, I'd rather pass a reference to their container.

I've been looking all over and tried a bunch of things, but can't seem to find an answer to this question anywhere. I know it is possible to amend attributes, reference resources and read class attributes, but is it possible to read attributes of a resource/defined type? If it isn't what is then the best possible work around?

like image 981
Lodewijk Bogaards Avatar asked Sep 25 '13 19:09

Lodewijk Bogaards


2 Answers

I've actually just found out that Puppetlab's stdlib module includes a getparam function that can be used to solve this problem.

So here is finally the solution to my own question:

define foo($x, $y) {
}

define bar($foo) {
  notify { getparam(Foo[$foo], 'x'): }
  notify { getparam(Foo[$foo], 'y'): }
}

foo { 'a':
  x => 'oh bar may you reference me',
  y => 'please'
}

bar { 'b':
  foo  => 'a'
}

Please note that the require => Foo['a'] in the definition of Bar['b'] does not appear to be needed.

like image 107
Lodewijk Bogaards Avatar answered Nov 15 '22 10:11

Lodewijk Bogaards


It doesn't seem that you can access a defined type's attributes. Possible explanation here. What you can do however, is externalize it via hiera.

Hiera is a great way to separate your manifest logic from the data populating it, but it is not difficult to set up.

Installing

In my first try I was trying to access hiera variables by class reference; foo::a for example, but that doesn't work for defined types.

Using http://drewblessing.com/blog/-/blogs/puppet-hiera-implement-defined-resource-types-in-hiera as a guide, you can put declare all those attributes in hiera with a simple config:

Configuring:

hiera.yaml

:backends:
  - yaml
:yaml:
  :datadir: $hiera_dir
:hierarchy:
  - common

$hiera_dir/common.yaml

foo:
  a:
    x: 'oh bar may you reference me'
    y: 'please'

And then in your puppet manifest:

define foo ($x, $y) {
}

define bar($foo) {
    require create_my_foos

    $all_foos = hiera('foo')

    # This is just for proof of concept, to show that the variable can be passed.
    file { '/tmp/output.txt':
        content => $all_foos[$foo]['x']
    }
}

class create_my_foos {  
    $foo_instances = hiera('foo', [])
    create_resources('foo', $foo_instances)
}

bar { 'b':
    foo => 'a'
}

Now you can access foo's variables by calling the hiera('foo') function to get an array of foo's attributes, and do array lookups to get the exact parameter you need.

Note that hiera only looks up top-level keys, so you can't do hiera('foo'['a']['x]).

like image 24
xiankai Avatar answered Nov 15 '22 11:11

xiankai