Theo Cabrerizo Diem
2011-Nov-16 15:16 UTC
[Puppet Users] define-type resources "default" parameters not available under scope.catalog.resources
Hi All, I have a define-type resource, which gets called from multiple classes, on which I would like to read its parameters from a template. This works for parameters added to the call of the resource but not for those which have a "default" value on its definition. On the example below, I can read the parameter from Webdir[c] but not from a and b. If webdir would be a class type instead (and with the restriction of being able to call it only once) it would work, since resource("Webdir[a]").parameters includes the ones set by default on the class definition. Is this intended or a bug ? I know that using a native define-type (those written in ruby) I can access the parameters as intended but, like the example below, it is nice to have the simplicity for doing the same on define-type resources when they contain other resources such as file, services, vcsrepo, etc. Here is some minimalist puppet file and template of what I''m trying to do : == site.pp =define webdir ( $dirname = $name, $access_mode = "private" ) { file { "/tmp/${dirname}": ensure => ''directory'', } } class webhost { file { "/tmp/apache.conf": ensure => ''present'', content => template(''/tmp/apache.erb''), } } node ''centos1'' { webdir { ''a'': } webdir { ''b'': } webdir { ''c'': access_mode => ''private'', } include webhost } === apache.erb ==<Virtualhost *:80> blablabla <% scope.catalog.resource_keys.select { |r,name| r == "Webdir"}.each do |r,name| -%> Alias /webdir/<%= name %> /tmp/<%= name %> <Directory /tmp/<%= name -%>> <% if scope.findresource("#{r}[#{name}]")[''access_mode''] == "private" then -%> require valid-user <% end -%> </Directory> <% end -%> </Virtualhost> === output of apache.erb ==<Virtualhost *:80> blablabla Alias /webdir/c /tmp/c <Directory /tmp/c> require valid-user </Directory> Alias /webdir/a /tmp/a <Directory /tmp/a> </Directory> Alias /webdir/b /tmp/b <Directory /tmp/b> </Directory> </Virtualhost> ====== Cheers, Theo -- You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com. To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.
jcbollinger
2011-Nov-16 22:13 UTC
[Puppet Users] Re: define-type resources "default" parameters not available under scope.catalog.resources
On Nov 16, 9:16 am, Theo Cabrerizo Diem <d...@carpediem.sh> wrote:> Hi All, > > I have a define-type resource, which gets called from multiple classes, on > which I would like to read its parameters from a template. This works for > parameters added to the call of the resource but not for those which have a > "default" value on its definition. > > On the example below, I can read the parameter from Webdir[c] but not from > a and b. > If webdir would be a class type instead (and with the restriction of being > able to call it only once) it would work, since > resource("Webdir[a]").parameters includes the ones set by default on the > class definition. > > Is this intended or a bug ?I don''t know, but parameterized classes do not serve as a reasonable reference for how defined type instances should behave. I do suspect, however, that the behavior you observe is not only intended, but also consistent with the behavior of native resource instances (see below).> I know that using a native define-type (those written in ruby) I can access > the parameters as intendedReally? I''m not a big templating guy, but if you declare, say service { ''frob'': enable => true } then what does the following template output? "<%= scope.findresource("Service[frob]")[''hasstatus''] -%>" The built-in Service type defines a default value for its hasstatus property, but I predict (instead of testing ... dangerous :-) ) that the template will evaluate to a blank / empty string. That would be exactly analogous to your case.> but, like the example below, it is nice to have > the simplicity for doing the same on define-type resources when they > contain other resources such as file, services, vcsrepo, etc.I understand, but really you ought to go at it a different way. A lot of people seem inclined to want in one part of their manifests to interrogate Puppet about what they themselves declared in a different part of their manifests. With some notable exceptions, that is a Puppet anti-pattern. For the case at hand, I would recommed using the Concat module to build your httpd configuration from pieces. Each webdir instance would declare an appropriate fragment, using the knowledge it already has about its own parameter values. Alternatively, you could let each webdir manage its piece of the configuration as a separate file, and make httpd.conf (or whatever) interpolate them all. John -- You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com. To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.
Theo Cabrerizo Diem
2011-Nov-18 15:03 UTC
Re: [Puppet Users] Re: define-type resources "default" parameters not available under scope.catalog.resources
As suggested, I''ve looked at the concat module, which I''ve made comments at the end - just to maintain the same flow of information as on previous conversations. On 16 November 2011 23:13, jcbollinger <John.Bollinger@stjude.org> wrote:> > > On Nov 16, 9:16 am, Theo Cabrerizo Diem <d...@carpediem.sh> wrote:> I > know that using a native define-type (those written in ruby) I can access > > the parameters as intended > > > Really? I''m not a big templating guy, but if you declare, say > > service { ''frob'': enable => true } > > then what does the following template output? > > "<%= scope.findresource("Service[frob]")[''hasstatus''] -%>" > > The built-in Service type defines a default value for its hasstatus > property, but I predict (instead of testing ... dangerous :-) ) that > the template will evaluate to a blank / empty string. That would be > exactly analogous to your case. >I''ve tested your suggestion and yes, the template return an empty string. Spending a bit of more time into this matter (because accidentally I had it working somehow - see below) define foo ($myparam = "Hello") { notice(inline_template("<%= scope.findresource(''Foo[${name}]'')[''myparam''] %>")) } node ''default'' { foo { ''test1'': } foo { ''test2'': } foo { ''test3'': myparam => "World", } } This will produce: notice: Scope(Foo[test1]): Hello notice: Scope(Foo[test2]): Hello notice: Scope(Foo[test3]): World Which means my problem is accessing the scope where a given instance of a resource is located. I''ve tried to browse through the "obvious" scope.findresource(''Foo[test1]'').scope but that did not help. Is there a way to access such a thing ? I''m not that much of a ruby expert, but I wonder how full-qualified variables are resolved. If someone could point it out or care to explain I would be grateful. I know the code above is useless as it is, but my point is to be able to iterate through given resources of a node in a template, allowing great flexibility inside a template, without the artifacts that concat module generates (and its drawbacks). I would imagine its goal would be similar to a exported resource, but locally and immediately available (not only after the node reported its exported resources) I understand, but really you ought to go at it a different way. A lot> of people seem inclined to want in one part of their manifests to > interrogate Puppet about what they themselves declared in a different > part of their manifests. With some notable exceptions, that is a > Puppet anti-pattern. >I think understand the point, but I believe I''m trying in the end to achieve what concat does without needing to deploy multiple files to the node and run a exec in the end ?> > For the case at hand, I would recommed using the Concat module to > build your httpd configuration from pieces. Each webdir instance > would declare an appropriate fragment, using the knowledge it already > has about its own parameter values. Alternatively, you could let each > webdir manage its piece of the configuration as a separate file, and > make httpd.conf (or whatever) interpolate them all. >I''ve used "webdir" and "apache" as a generic example since it would make easier to understand what I''m trying to deal with. Not every configuration file supports includes with filename expansion or "dot d" directories. I''ve looked into concat module (thank you for suggesting it) and implemented into my manifests to the point that it worked as intended, but although I don''t have a better solution available at the moment, I''m not happy on having things such as : concat::fragment { "config_footer": target => $myconfigfile, content => "</Virtualhost>" order => 99, } Since it gets hard to track when you start to have variations on the "tree structure" of your config file, which IMHO, gets much easier to handle when you use blocks in a single erb template. Cheers, Theo> > > John > > -- > You received this message because you are subscribed to the Google Groups > "Puppet Users" group. > To post to this group, send email to puppet-users@googlegroups.com. > To unsubscribe from this group, send email to > puppet-users+unsubscribe@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/puppet-users?hl=en. > >-- You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com. To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.
jcbollinger
2011-Nov-18 22:16 UTC
[Puppet Users] Re: define-type resources "default" parameters not available under scope.catalog.resources
On Nov 18, 9:03 am, Theo Cabrerizo Diem <d...@carpediem.sh> wrote: [...]> > define foo ($myparam = "Hello") { > notice(inline_template("<%= scope.findresource(''Foo[${name}]'')[''myparam''] > %>"))} > > node ''default'' { > foo { ''test1'': } > foo { ''test2'': } > foo { ''test3'': myparam => "World", } > > } > > This will produce: > notice: Scope(Foo[test1]): Hello > notice: Scope(Foo[test2]): Hello > notice: Scope(Foo[test3]): World > > Which means my problem is accessing the scope where a given instance of a > resource is located.Naturally, a template called from inside the defined type''s body has access to the instance''s parameter values, including defaulted ones. Most people would just use them as simple variables, however, rather than looking them up via the scope object. In fact, I''m inclined to call ''bug'' on this one: it should never be the case that <%scope.findresource(''Foo[bar]'')[''myparam''] %> can be evaluated without error to return two different values in the same catalog run. In any case, I don''t see why you suppose that the values you want will remain accessible outside the definition body. It was worth a try, certainly, but if the lookup you have already attempted does not do the job then I can''t imagine what would.> [...] > I know the code above is useless as it is, but my point is to be able to > iterate through given resources of a node in a template, allowing great > flexibility inside a template, without the artifacts that concat module > generates (and its drawbacks).I understand why you want to do what you ask, but I just don''t think Puppet supports it. Feel free to submit a feature request. John -- You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com. To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.