Enable fail to be used within the case of a selector

263 views
Skip to first unread message

Sage Imel

unread,
Mar 19, 2014, 12:31:56 AM3/19/14
to puppe...@googlegroups.com
With the future parser enabling selectors to used in the case of another selector it's possible to use selectors to specialize on multiple facts or other values very concisely.

$puppet_conf_file_path = $::osfamily ? {
  'Debian' => $::operatingsystem ? {
    'Ubuntu' => '/pretending/ubuntu/is/special/here'/puppet/puppet.conf',
    default   => '/pretending/debian/in/general/is/special/in/a/different/way/here/puppet/puppet.conf',
  default => '/etc/puppet/puppet.conf'
}

But sometimes setting a default value is not the desired behavior for unmatched cases. Sometimes, like in a params class, you'd rather just fail the whole puppet run when an unmatched case is hit.

class
puppet::params(
   # In this case we are only specializing based on one parameter
   $conf_file_path = $::osfamily ? {
     'Debian' => '/etc/puppet/puppet.conf',
     default => fail("osfamily ${::osfamily} is not supported by this module"),
   },
   #in this case we are specializing based on multiple parameters
   $vardir = $::osfamily ? {
     'Debian' => $operatingsystem ? {
       'Debian' => '/var/lib/puppet',
       default => fail("operatingsystem ${::operatingsystem} is not supported by this module"),
     },
     default => fail("osfamily ${::osfamily} is not supported by this module"),
   },
){}

This almost works with the future parser. Except that puppet errors out on the cases that hit the fail call because the fail function doesn't return an rvalue.

Making it possible to use fail in selectors would make this pattern very versatile and could greatly simplify params classes. You can set the parameters in all valid cases and throw errors with messages that are tailored to the exact context without having to repeat logic or variable names. This pattern also lets you see for sure at a glance that a parameter is being set (or that the run will fail) which is harder to see when doing the same thing with conds since you have to examine all the case blocks.

The easier way to make this work would probably be to make fail return a value (maybe the error message that would be shown). But it doesn't make sense to me that fail should check if it's expected to yield an rvalue since fail completely changes the flow of execution and will would never make it to returning a value anyways, so making the change there makes more sense to me.

Andy Parker

unread,
Mar 19, 2014, 12:24:01 PM3/19/14
to puppe...@googlegroups.com
On Tue, Mar 18, 2014 at 9:31 PM, Sage Imel <night...@gmail.com> wrote:
With the future parser enabling selectors to used in the case of another selector it's possible to use selectors to specialize on multiple facts or other values very concisely.


Sage, thanks for trying out the future parser and giving us feedback.
 
$puppet_conf_file_path = $::osfamily ? {
  'Debian' => $::operatingsystem ? {
    'Ubuntu' => '/pretending/ubuntu/is/special/here'/puppet/puppet.conf',
    default   => '/pretending/debian/in/general/is/special/in/a/different/way/here/puppet/puppet.conf',
  default => '/etc/puppet/puppet.conf'
}

But sometimes setting a default value is not the desired behavior for unmatched cases. Sometimes, like in a params class, you'd rather just fail the whole puppet run when an unmatched case is hit.

class
puppet::params(
   # In this case we are only specializing based on one parameter
   $conf_file_path = $::osfamily ? {
     'Debian' => '/etc/puppet/puppet.conf',
     default => fail("osfamily ${::osfamily} is not supported by this module"),
   },
   #in this case we are specializing based on multiple parameters
   $vardir = $::osfamily ? {
     'Debian' => $operatingsystem ? {
       'Debian' => '/var/lib/puppet',
       default => fail("operatingsystem ${::operatingsystem} is not supported by this module"),
     },
     default => fail("osfamily ${::osfamily} is not supported by this module"),
   },
){}


You are right, this doesn't work in 3.4.3. If you try out 3.5.0-rc1 we've starting implementing a new language evaluator that can do this. Here is an example:

  > cat t.pp
  $x = $kernel ? { default => fail("no!") }
  [09:21:23][Ruby(ruby-1.8.7-p374)][Git(stable)] andy:puppet
  > be puppet apply t.pp --parser future
  Error: no! on node aparker.corp.puppetlabs.net
  Error: no! on node aparker.corp.puppetlabs.net
 
This almost works with the future parser. Except that puppet errors out on the cases that hit the fail call because the fail function doesn't return an rvalue.

Making it possible to use fail in selectors would make this pattern very versatile and could greatly simplify params classes. You can set the parameters in all valid cases and throw errors with messages that are tailored to the exact context without having to repeat logic or variable names. This pattern also lets you see for sure at a glance that a parameter is being set (or that the run will fail) which is harder to see when doing the same thing with conds since you have to examine all the case blocks.

The easier way to make this work would probably be to make fail return a value (maybe the error message that would be shown). But it doesn't make sense to me that fail should check if it's expected to yield an rvalue since fail completely changes the flow of execution and will would never make it to returning a value anyways, so making the change there makes more sense to me.

We are removing the rvalue vs. statement distinction for functions in the future parser/evaluator work and the distinction will be gone in puppet 4. Having the distinction did little more than cause confusion and frustration, as you just experienced.
 

--
You received this message because you are subscribed to the Google Groups "Puppet Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to puppet-dev+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-dev/fb703326-16d2-4024-94be-561a7ab786b7%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Andrew Parker
Freenode: zaphod42
Twitter: @aparker42
Software Developer

Join us at PuppetConf 2014September 23-24 in San Francisco - http://bit.ly/pupconf14
Reply all
Reply to author
Forward
0 new messages