Puppet unless behaviour with a dependency

677 views
Skip to first unread message

jimbob palmer

unread,
Feb 17, 2012, 10:12:46 AM2/17/12
to puppet...@googlegroups.com
Is this really expected behaviour? Should the second Exec succeed even if the first never runs?

exec { "one":
 command => "/bin/true",
 unless => '/bin/false'
}
exec { "two":
 command => "/bin/true",
 require => Exec["one"],
}

jimbob palmer

unread,
Feb 17, 2012, 10:15:15 AM2/17/12
to puppet...@googlegroups.com
Sorry:


exec { "one":
 command => "/bin/true",
 unless => '/bin/true'

R.I.Pienaar

unread,
Feb 17, 2012, 10:19:02 AM2/17/12
to puppet...@googlegroups.com

I think this is https://projects.puppetlabs.com/issues/5876

i think this is a major failure of Puppet to honour what people expect
and what the language suggests in the choice of meta param names etc
but there's some debate in that ticket

jimbob palmer

unread,
Feb 17, 2012, 10:41:58 AM2/17/12
to Puppet Users
On Feb 17, 4:19 pm, "R.I.Pienaar" <r...@devco.net> wrote:
> ----- Original Message -----
> > From: "jimbob palmer" <jimbobpal...@gmail.com>
> > To: puppet...@googlegroups.com
> > Sent: Friday, February 17, 2012 3:12:46 PM
> > Subject: [Puppet Users] Puppet unless behaviour with a dependency
>
> > Is this really expected behaviour? Should the second Exec succeed
> > even if the first never runs?
>
> > exec { "one":
> > command => "/bin/true",
> > unless => '/bin/false'
> > }
> > exec { "two":
> > command => "/bin/true",
> > require => Exec["one"],
> > }
>
> I think this ishttps://projects.puppetlabs.com/issues/5876
>
> i think this is a major failure of Puppet to honour what people expect
> and what the language suggests in the choice of meta param names etc
> but there's some debate in that ticket

It's causing me a real headache.

I need to run an expensive command if a string is not present in a
file. If the string is present, I abort. That expensive command
finishes by writing the string to the file.

If the expensive command runs I need to run a second command, which is
also expensive to run.

How can I do this? If I duplicate the unless the second command can
never run since the string will be present in the file.

jimbob palmer

unread,
Feb 17, 2012, 11:01:56 AM2/17/12
to Puppet Users
This also doesn't work :(
command => "/bin/true; /bin/second_command"

Adam Heinz

unread,
Feb 17, 2012, 11:12:59 AM2/17/12
to puppet...@googlegroups.com
Something like this?

exec { "second command":
refreshonly => true,
subscribe => Exec["first command"],
}

jimbob palmer

unread,
Feb 17, 2012, 11:22:17 AM2/17/12
to Puppet Users
Gah! I'm five minutes behind you. It works - THANKS.

jcbollinger

unread,
Feb 17, 2012, 5:03:22 PM2/17/12
to Puppet Users


On Feb 17, 9:19 am, "R.I.Pienaar" <r...@devco.net> wrote:
> ----- Original Message -----
> > From: "jimbob palmer" <jimbobpal...@gmail.com>
> > To: puppet...@googlegroups.com
> > Sent: Friday, February 17, 2012 3:12:46 PM
> > Subject: [Puppet Users] Puppet unless behaviour with a dependency
>
> > Is this really expected behaviour? Should the second Exec succeed
> > even if the first never runs?
>
> > exec { "one":
> > command => "/bin/true",
> > unless => '/bin/false'
> > }
> > exec { "two":
> > command => "/bin/true",
> > require => Exec["one"],
> > }
>
> I think this ishttps://projects.puppetlabs.com/issues/5876


No, I don't think this is 5876. That involves an Exec that 'require's
a *failing* resource, but which runs anyway because it also
'subscribe's to resources that are applied successfully. This case is
quite different: Exec['two'] depends on a resource that *succeeds*,
therefore there is no reason why it should not run.

The key point here is that the 'unless' and 'onlyif' parameters of an
Exec never themselves cause that Exec to fail. Instead, they are
among an Exec's ways of determining whether it is already in sync, and
a resource that is already in sync succeeds trivially. If the Exec is
not already in sync then its command is run, and its success is judged
by the return value.


> i think this is a major failure of Puppet to honour what people expect
> and what the language suggests in the choice of meta param names etc
> but there's some debate in that ticket


I think 5876 is a real problem, but not so much the issue presented
here. People can evidently be taken by surprise, but I rate that a
documentation issue. The behavior itself is sensible and desirable.
Moreover, the alternative is already available by putting the
condition into the command, like so:

exec { 'example': command => '/usr/bin/
fail_when_the_command_shouldnt_run && /usr/bin/the_command' }

As the OP discovered, the alternative can also be achieved via
subscribe / notify.


John

jimbob palmer

unread,
Feb 20, 2012, 5:39:20 AM2/20/12
to Puppet Users
On Feb 17, 5:22 pm, jimbob palmer <jimbobpal...@gmail.com> wrote:
The problem that this creates is that *any* update now runs the
command from the subscribe, which isn't ideal, but I guess will work
for now :)

jcbollinger

unread,
Feb 20, 2012, 10:03:10 AM2/20/12
to Puppet Users
I don't follow. Do you mean that if any resource at all on the target
node is updated by Puppet, then the second Exec runs? That should not
be. An Exec marked with "refreshonly => true" should only run if it
receives a signal.

Or do you mean that the *first* command is executing on every Puppet
run? That's not influenced by the DSL fragment you quoted.

Here's a complete example that should work:

====
class test::manage_my_file {
$my_file = '/tmp/test'
$target_string = 'So long, and thanks for all the fish'

file { "${my_file}": ensure => 'file' }

exec { 'command_one':
command => "echo '${target_string}' >> ${my_file}",
unless => "grep -q '${target_string}' ${my_file}",
require => File["${my_file}"]
}

exec { 'command_two':
command => "/bin/cp ${my_file} /tmp/test2",
refreshonly => true,
subscribe => Exec[ 'command_one' ]
}
}

node default {
include 'test::manage_my_file'
}
====

With that as your site.pp (to exclude any possibility of influence by
other manifest files), you should see Exec['command_one'] run unless
the string "So long, and thanks for all the fish" is present in file /
tmp/test on the target node (any target node). If Exec['command_one']
runs then Exec['command_two'] should run after. If
Exec['command_one'] *does not* run, then neither should
Exec['command_two'].

If Exec['command_one'] runs when /tmp/test already contains the target
string, or if Exec['command_two'] runs when Exec['command_one'] did
not first run in the same session, then you should file a bug report.

If this approach does not appear to work when you adapt it to your
problem, then do check at least these things:
1) that your 'unless' command is exiting with the expected return
code. If it always returns a false (non-zero) exit code then the two
execs will always run.
2) that no other resource is set to 'notify' Exec['command_two']. If
you use resource defaults anywhere in your configuration then don't
forget to check those, too. Also, beware of any resource notifying a
collection of Execs, as such a collection could easily include
Exec['command_two'] without explicitly naming it.


John
Reply all
Reply to author
Forward
0 new messages