access exported resources in template

1,269 views
Skip to first unread message

Bernhard Bock

unread,
Oct 19, 2009, 9:19:43 AM10/19/09
to puppet...@googlegroups.com
Hi,

I'm trying to develop a class that autogenerates a config file based
on an .erb template.
It shall populate the config file with data exported from various hosts.

Some pseudocode to clarify my issue:

node n1 {
@@mytype {
"name":
property => "foo"
}
}

template.erb:
<% mytype.each do |bar| %>
<%= bar.name %>
<%= bar.property %>
<% end %>

My question is: How can I access and iterate through the exported
resources in the template? mytype.each will not work...

best regards
Bernhard

Luke Kanies

unread,
Oct 21, 2009, 12:55:37 AM10/21/09
to puppet...@googlegroups.com


This is getting into semi-supported internal APIs, but you can get the
resource list from the catalog, something like this:

compiler.catalog.vertices.each do |resource|
resource.title
resource[:property]
end

--
What happens to the hole when the cheese is gone? -- Bertolt Brecht
---------------------------------------------------------------------
Luke Kanies | http://reductivelabs.com | http://madstop.com

Sven Mueller

unread,
Oct 21, 2009, 6:34:05 AM10/21/09
to puppet...@googlegroups.com

Luke Kanies schrieb:


> On Oct 19, 2009, at 6:19 AM, Bernhard Bock wrote:
>
>> Hi,
>>
>> I'm trying to develop a class that autogenerates a config file based
>> on an .erb template.
>> It shall populate the config file with data exported from various
>> hosts.
>>
>> Some pseudocode to clarify my issue:
>>
>> node n1 {
>> @@mytype {
>> "name":
>> property => "foo"
>> }
>> }
>>
>> template.erb:
>> <% mytype.each do |bar| %>
>> <%= bar.name %>
>> <%= bar.property %>
>> <% end %>
>>
>> My question is: How can I access and iterate through the exported
>> resources in the template? mytype.each will not work...
>
> This is getting into semi-supported internal APIs, but you can get the
> resource list from the catalog, something like this:
>
> compiler.catalog.vertices.each do |resource|
> resource.title
> resource[:property]
> end

Being semi-supported or not, can I get to this from a template? I tried
with lookupvar('compiler') and lookupvar('compiler.catalog.vertices'),
but lookupvar returns not the variable, but a string. And that is empty
in both cases. Do I need to define my own function to return something
more useful?
Also: how can I check which type the resource has? "resource.type" seems
wrong (as I expect that the ruby Type is not the same as the type)?

The idea Bernhard had, if I understand it correctly, is to use a custom
type just to store the wanted data (and being a type, not a variable,
many instances can exist and get exported). The data is then collected
by a template. For me, this has two advantages (over other solutions
available to collect data from multiple hosts):
1) The user can change the template as needed
2) The resulting file is not edited, but recreated on each run, so its
content is deterministic after the run, even if someone edited it
manually beforehand.

Regards,
Sven

Ohad Levy

unread,
Oct 21, 2009, 8:38:48 AM10/21/09
to puppet...@googlegroups.com
I've recently added a similar functionality to foreman - it allows you to query within puppet (or externally via a script) to get back a list of hosts that answer to a certain criteria.

Currently, one can query for a hosts that belong to a certain class or has a certain fact, e.g.

in a template you can do:
<% foreman_function("fact=RedHat").each do |host| -%>
something will all my redhat machines goes here..
..
<% end -%>

Ohad

p.s. its not yet in the stable release...
http://theforeman.org

Luke Kanies

unread,
Oct 21, 2009, 2:35:53 PM10/21/09
to puppet...@googlegroups.com

Ah; I think you need scope.compiler.catalog, sorry. We should make
that visible within the template, I guess.

> Also: how can I check which type the resource has? "resource.type"
> seems
> wrong (as I expect that the ruby Type is not the same as the type)?

It actually is 'resource.type' - Ruby has deprecated 'type' as a means
of getting the class, so I was comfortable using it.

> The idea Bernhard had, if I understand it correctly, is to use a
> custom
> type just to store the wanted data (and being a type, not a variable,
> many instances can exist and get exported). The data is then collected
> by a template. For me, this has two advantages (over other solutions
> available to collect data from multiple hosts):
> 1) The user can change the template as needed
> 2) The resulting file is not edited, but recreated on each run, so its
> content is deterministic after the run, even if someone edited it
> manually beforehand.


The downsides, though, are that you're directly mapping the resource
to a file, which is a bit limited unless you're using file fragments
of some kind. And if you're doing that, why not just export a defined
type that generates the file with a normal template?

--
Between two evils, I always pick the one I never tried before.
-- Mae West

Luke Kanies

unread,
Sep 7, 2012, 12:52:04 AM9/7/12
to puppet...@googlegroups.com, lu...@madstop.com
Wow, talk about a blast from the past.  I don't get a lot of replies to 3 year old email. :)

What happens when you do this?  It looks like it should basically work, although I'd use 'resources' instead of 'vertices', I think.  What version is this?

On Sep 6, 2012, at 10:14 AM, ctrlc-root <root....@gmail.com> wrote:

The resource[:property] method doesn't seem to work. I'm pretty new with puppet and only just learned ruby, so I was hoping someone could perhaps just point me in the right direction. Here's what I've got so far:

<% scope.compiler.catalog.vertices.each do |resource| -%>
<% if resource.type == "Firewall::Rule" -%> 
# <%= resource[:comment] %>
<% end -%> 
<% end -%>

where Firewall::Rule is defined something like:

define firewall::rule ($comment=$title){}

Any ideas?
--
You received this message because you are subscribed to the Google Groups "Puppet Users" group.
To view this discussion on the web visit https://groups.google.com/d/msg/puppet-users/-/1mmfEPyDYj4J.
To post to this group, send email to puppet...@googlegroups.com.
To unsubscribe from this group, send email to puppet-users...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.


ctrlc-root

unread,
Sep 7, 2012, 9:01:13 AM9/7/12
to puppet...@googlegroups.com, lu...@madstop.com
Well, 3 years old or not, this is still in the first page of google results haha. I'm running puppet version 2.7.9 and the result of that template is a blank comment line for every instance of the Firewall::Rule type. If I replace 'resource[:comment]' with 'resource.type' then I can confirm that the iteration is actually working, because I see comment lines like this '# Firewall::Rule'. I tried 'resources["comment"]', 'resources[:comment]', and 'resources.comment' (with this one triggering an error).

I wish there was some easy way to get an interactive ruby shell running with the same environment so I could actually test this without running puppet apply every time, if I could I probably would have figured it out on my own already. If you don't know what the answer is, could you maybe point me in the general direction of how you would find out? Perhaps a relevant part of the puppet source code? And thanks for answering.


On Friday, September 7, 2012 12:52:14 AM UTC-4, Luke Kanies wrote:
Wow, talk about a blast from the past.  I don't get a lot of replies to 3 year old email. :)

What happens when you do this?  It looks like it should basically work, although I'd use 'resources' instead of 'vertices', I think.  What version is this?

-- 

Luke Kanies

unread,
Sep 9, 2012, 5:35:31 PM9/9/12
to puppet...@googlegroups.com, ctrlc-root
I don't quite know the answer, and I agree, a running shell would be useful.

I'd be looking in Parser::Scope and the TemplateWrapper class, wherever it is.  Those should generally cover it, with maybe Parser::Resource.

You should try deeper inspection of the resources.  I think 'resource.to_hash' should give you all of the resource's parameters.

--
You received this message because you are subscribed to the Google Groups "Puppet Users" group.
To view this discussion on the web visit https://groups.google.com/d/msg/puppet-users/-/XEXWIRbxz9kJ.

To post to this group, send email to puppet...@googlegroups.com.
To unsubscribe from this group, send email to puppet-users...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.

Vasiliy Boulytchev

unread,
Jun 27, 2013, 2:29:03 PM6/27/13
to puppet...@googlegroups.com
any solutions? :)

Vasiliy Boulytchev

unread,
Jun 27, 2013, 2:30:42 PM6/27/13
to puppet...@googlegroups.com
Sir, have you been able to find a solution?


On Monday, October 19, 2009 9:19:43 AM UTC-4, Bernhard Bock wrote:

jcbollinger

unread,
Jun 28, 2013, 9:18:24 AM6/28/13
to puppet...@googlegroups.com


On Thursday, June 27, 2013 1:30:42 PM UTC-5, Vasiliy Boulytchev wrote:
Sir, have you been able to find a solution?


The approach the OP proposed is not supported by Puppet.  Among the alternatives are:
  • Use the Concat module.  This allows each contributing node to export one or more resources that represent fragments of the target file, which are collected and assembled for the node(s) that needs the whole target file.  The fragments can be formatted via templates, but their assembly does not use a template (and therefore does not involve iterating a collection or accessing anything therein from a template).
  • Record the needed data in an accessible external store in the first place, so that the target node can load it via Hiera (or another data access function) instead of trying to use exported resources as a vehicle for data.
  • Use a data access function in your template to query puppetdb (supposing you are using Puppet 3) to extract the data you want about other nodes' exported resources.
Of those, I would look first at Concat.


John

Reply all
Reply to author
Forward
0 new messages