Variable interpolation in class parameters

360 views
Skip to first unread message

Carlos Sanchez

unread,
Sep 29, 2011, 11:07:20 AM9/29/11
to puppet...@googlegroups.com
Hi,

In class parameters, things like x="x", y="y${x}" don't always evaluate right (y="yx"), seems random. I'm using 2.7.1

class test1(
    $servicex = "sonar",
    $logfoldera = "${homex}/logs",
    $logfoldere = "${homey}/logs",
    $logfolderh = "${homez}/logs",
    $logfolder = "${homex}/logs",
    $homex = "/var/${servicex}",
    $homey = "/var/${servicex}",
    $homez = "/var/${servicex}") {

    notice($homex)
    notice($homey)
    notice($homez)
    notice("-----")
    notice($logfoldera)
    notice($logfoldere)
    notice($logfolderh)
}


output :

notice: Scope(Class[Test1]): /var/sonar
notice: Scope(Class[Test1]): /var/sonar
notice: Scope(Class[Test1]): /var/sonar
notice: Scope(Class[Test1]): -----
notice: Scope(Class[Test1]): /var/sonar/logs
notice: Scope(Class[Test1]): /logs
notice: Scope(Class[Test1]): /logs


Note the last two messages should print "/var/sonar/logs"
Ordering the paramenters in the order they are needed gets the same result.

Just by changing the name of the parameters from class test1 to test2 I get different evaluations of the variables, one is right and two are wrong, you can see that in this gist https://gist.github.com/1250837

Am I doing something wrong? is interpolation not supposed to work with class parameters?


Thanks


Cody Herriges

unread,
Sep 29, 2011, 1:01:32 PM9/29/11
to puppet...@googlegroups.com
Carlos,

This seems to be a bug as things be weirder the more I test.

class test1(
$servicex = 'servicex',
$servicey = 'servicey',
$service1 = "/bar/${servicex}",
$service2 = "/bar/${servicey}",
$homex = 'homex',
$home1 = "/bar/${homex}"
) {

notice($service1)
notice("-----")
notice($service2)
notice("-----")
notice($home1)
}

include test1

Gets the output of:

notice: Scope(Class[Test1]): /bar/servicex


notice: Scope(Class[Test1]): -----

notice: Scope(Class[Test1]): /bar/servicey


notice: Scope(Class[Test1]): -----

notice: Scope(Class[Test1]): /bar/

If you add underscores in the variable names like so:

class test1(
$service_x = 'servicex',
$service_y = 'servicey',
$service1 = "/bar/${service_x}",
$service2 = "/bar/${service_y}",
$homex = 'homex',
$home1 = "/bar/${homex}"
) {

notice($service1)
notice("-----")
notice($service2)
notice("-----")
notice($home1)
}

include test1

You get this response:

notice: Scope(Class[Test1]): /bar/


notice: Scope(Class[Test1]): -----

notice: Scope(Class[Test1]): /bar/


notice: Scope(Class[Test1]): -----

notice: Scope(Class[Test1]): /bar/

This is most obviously a scoping issue and the fact that service is being treated special makes me think a magic service variable is being set someplace internally.

> --
> 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/-/ubA3F3GClqcJ.
> 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.

jcbollinger

unread,
Sep 30, 2011, 11:50:33 AM9/30/11
to Puppet Users
> can see that in this gisthttps://gist.github.com/1250837
>
> Am I doing something wrong? is interpolation not supposed to work with class
> parameters?


I do think there's a bug, but I'm not confident it's the one you think
it is. I find no documentation of any difference in variable
interpolation in class parameter defaults than in any other context,
so I expect the interpolation to be performed according to the same
rules as elsewhere. Specifically, I expect interpolation to draw on
only variables available in the scope in which the host string
appears. A class's parameters cannot be in scope in that class's own
parameter list definition, because their values are not known at that
point. Therefore, you should not be able to interpolate one
parameter's actual value into the default value of a another
parameter. That is, NONE of the interpolations in your example should
work.

You can, however, do this:

class test1(
$servicex = "sonar",
$logfolderxpar = "",
$homexpar = "") {

$homex = ${homexpar} ? { "" => "/var/${servicex}", default => $
{homexpar} }
$logfolderx = ${logfolderxpar} ? { "" => "${homex}/logs", default
=> ${logfolderxpar} }

# ...
}


John

Carlos Sanchez

unread,
Oct 1, 2011, 1:02:43 PM10/1/11
to puppet...@googlegroups.com
I have created an issue at http://projects.puppetlabs.com/issues/9848 for reference

Steve Shipway

unread,
Oct 31, 2011, 10:55:11 PM10/31/11
to puppet...@googlegroups.com
FWIW, I find I agree with jcbollinger on this one -- the class parameter declaration block is not a code block, so you should not use variables defined there to define other variables in the same block.  That it works at all is surprising, and probably down to the order the parameters are processes (which, as it most likely depends on hash table sequence, is going to appear random)

Best practice would seem to be to make the variables default to null, and then use subsequent evaluations within the class code to perform the relevant defaulting, as he said.

Steve



Al @ Lab42

unread,
Nov 8, 2011, 5:41:40 AM11/8/11
to puppet...@googlegroups.com


On Friday, September 30, 2011 4:50:33 PM UTC+1, jcbollinger wrote:
I do think there's a bug, but I'm not confident it's the one you think
it is.  I find no documentation of any difference in variable
interpolation in class parameter defaults than in any other context,
so I expect the interpolation to be performed according to the same
rules as elsewhere.  Specifically, I expect interpolation to draw on
only variables available in the scope in which the host string
appears.  A class's parameters cannot be in scope in that class's own
parameter list definition, because their values are not known at that
point.  Therefore, you should not be able to interpolate one
parameter's actual value into the default value of a another
parameter.  That is, NONE of the interpolations in your example should
work.
Hi John,
This thing scaries me a bit.
I'm rewriting my modules in order to merge the usage of a  params.pp  class where defaults are set and parametrized classes.
The output is something like :
class openssh (
[...]
  $package = $openssh::params::package,
  $service = $openssh::params::service,
  $service_status = $openssh::params::service_status,
  $process = $openssh::params::process,
  $process_args = $openssh::params::process_args,
  $config_dir = $openssh::params::config_dir,
  $config_file = $openssh::params::config_file,
  $config_file_mode = $openssh::params::config_file_mode,
  $config_file_owner = $openssh::params::config_file_owner,
  $config_file_group = $openssh::params::config_file_group,
  $config_file_init = $openssh::params::config_file_init,
  $pid_file = $openssh::params::pid_file,
  $data_dir = $openssh::params::data_dir,
  $log_dir = $openssh::params::log_dir,
  $log_file = $openssh::params::log_file
  ) inherits openssh::params {

There is no particular interpolation on variables, just their value's assignment as default.
Is this a supported behaviour that I can trust to be mantained on future versions?

Al

jcbollinger

unread,
Nov 8, 2011, 8:59:38 AM11/8/11
to Puppet Users
I do not work for PuppetLabs nor contribute code to Puppet. With that
said, however,

1) This precise approach is used in an example on the PuppetLabs
documentation site, and

2) it is not what this thread was previously discussing.

Specifically, this thread was not about generally using variables as
or in class parameters' default values; instead, it was about using
some of a class's *own* parameters as or in the default values of
others of that class's parameters. I haven't changed my mind on that
topic.

As to your approach, I think it should work now and in the future, in
the sense that it will reliably set the superclass variables' values
as the default values for the subclass's parameters. My personal
opinion, however, is that class parameterization is generally a bad
idea, that class inheritance should be used only for overriding
resource properties, and that going against both of those precepts at
the same time is ... something I can't see myself ever doing.


John
Reply all
Reply to author
Forward
0 new messages