Exec type's 'onlyif' and 'unless' commands run even with --noop

2,855 views
Skip to first unread message

Vladimir Brik

unread,
Sep 4, 2013, 9:01:31 AM9/4/13
to puppet...@googlegroups.com
Hello,

I have noticed that commands specified in 'onlyif' and 'unless'
parameters of the Exec type are always executed, even if --noop option
is given on command line or the resource's noop parameter is set to true.

For example, the following block always creates /tmp/onlyif and /tmp/unless.

exec{"touch /tmp/exec":
noop => true,
onlyif => "touch /tmp/onlyif",
unless => "touch /tmp/unless; false",
}

Is this expected behavior?

Is it possible to determine from within puppet manifest whether --noop
option has been given on command line? For example, to change the block
above to something like:

if ! $noop {
exec{"touch /tmp/exec":
onlyif => "touch /tmp/onlyif",
unless => "touch /tmp/unless; false",
}
}

Thanks,

Vlad

Dewey Sasser

unread,
Sep 4, 2013, 9:13:10 AM9/4/13
to puppet...@googlegroups.com, Vladimir Brik
On 9/4/2013 9:01 AM, Vladimir Brik wrote:
Hello,

I have noticed that commands specified in 'onlyif' and 'unless' parameters of the Exec type are always executed, even if --noop option is given on command line or the resource's noop parameter is set to true.

For example, the following block always creates /tmp/onlyif and /tmp/unless.

exec{"touch /tmp/exec":
        noop   => true,
        onlyif => "touch /tmp/onlyif",
        unless => "touch /tmp/unless; false",
}

Is this expected behavior?

Personally I would expect that behavior. 

When I use "--noop" I expect puppet to tell me what it would do without the flag, and it is necessary for it to execute predicates in order to determine that.

I would no more expect it not to execute the predicate procedures in an "exec" than I would expect it not to execute the custom fact procedures when executing facter (or expect it not to execute facter).

I consider predicates which modify the state of the system to be violating the contract of "predicate".  I don't expect puppet to work around this kind of contract violation, particularly when doing so would reduce the value to me.

I.e. I would expect to write

# NOTE:  example that ignores a lot of resiliency
exec { "echo %sudo ALL ALL >> /etc/sudoers":
   onlyif => "grep -v %sudo /etc/sudoers"
}

and if I execute it with the "--noop" flag I would expect it to tell me whether or not it would modify /etc/sudoers if I ran it without the flag.

--
Dewey

jcbollinger

unread,
Sep 5, 2013, 10:01:37 AM9/5/13
to puppet...@googlegroups.com


On Wednesday, September 4, 2013 8:01:31 AM UTC-5, Vladimir Brik wrote:
Hello,

I have noticed that commands specified in 'onlyif' and 'unless'
parameters of the Exec type are always executed, even if --noop option
is given on command line or the resource's noop parameter is set to true.

For example, the following block always creates /tmp/onlyif and /tmp/unless.

exec{"touch /tmp/exec":
         noop   => true,
         onlyif => "touch /tmp/onlyif",
         unless => "touch /tmp/unless; false",
}

Is this expected behavior?



Yes.  The --noop flag tells Puppet to determine which resources are out of sync, and to report them without actually synchronizing them.  The 'onlyif' and 'unless' commands of an Exec are used in the process of determining whether the Exec is already in sync, therefore they must be run during a --noop Puppet run.  The synchronization of an out-of-sync Exec resource involves only running the command given by its 'command' property, so that's the only part that --noop prevents.

 
Is it possible to determine from within puppet manifest whether --noop
option has been given on command line? For example, to change the block
above to something like:

if ! $noop {
        exec{"touch /tmp/exec":
                 onlyif => "touch /tmp/onlyif",
                 unless => "touch /tmp/unless; false",
        }
}




I don't think so.  As far as I know, the agent's command-line flags are not communicated to the master, so they cannot influence catalog compilation.

It sounds like you are trying to make the 'onlyif' and 'unless' commands serve a different purpose than they in fact do.  Those Exec parameters, along with 'creates', are Puppet's means for determining whether an Exec needs to be synchronized (which is performed, when needed, by executing the 'command' command).  This is important -- it matters for more than just --noop mode.  In particular, any resource that is already in sync succeeds automatically and does not broadcast events, so whether and how related resources are applied can be affected.

Perhaps what you really want is to incorporate the 'onlyif' and / or 'unless' commands into the main 'command'.  For example,

exec{ 'touch /tmp/onlyif && touch /tmp/unless || touch /tmp/exec':
  provider => 'sh'
}


Or it looks like your real desire may be for the exec to encompass all three commands, all the time:

exec{ 'touch /tmp/onlyif; touch /tmp/unless; touch /tmp/exec':
  provider => 'sh'
}

or even

exec{ 'bash -c "touch /tmp/onlyif; touch /tmp/unless; touch /tmp/exec"': }

Please do understand that these are semantically different than your original Exec.


John

Reply all
Reply to author
Forward
0 new messages