'require' option is ignored?

25 views
Skip to first unread message

buoyant_puppy

unread,
Feb 14, 2018, 11:31:33 AM2/14/18
to Puppet Users
This is an example I found online that would do what I want: check if a dir exists and if so, do something:

class foo {
  exec { "is foo present":
    command => "/bin/true",
    onlyif => "/usr/bin/test -d /foo"
  }
  file { "create a file if dir foo is present":
    path => "/path/otherfoo",
    ...snip...
    require => Exec["is foo present],
  }
}

But it doesn't work - the 'file' resource is always executed, regardless of whether the 'exec' resource returned true or false.
What am I missing?

buoyant_puppy

unread,
Feb 15, 2018, 5:41:59 AM2/15/18
to Puppet Users
I think I got this. My main issue was the 'true' logic with an 'onlyif', because that's always only going to either run (= and therefore meet the requirement) or not run at all (= which also meets the requirement since it's not a failure).

I feel the choice of words here leaves room for confusion. Like "unless"... unless succeeds? unless fails? "requires" also leaves some amgiuity as well, since it considers the requirement met as long as the required resource did not explicitly return a failure. So "notrun" is just as good as success, which to me doesn't really intuitively match what I think "require" means.

Here's a set of tests that illustrate all this more clearly, in case it helps someone else that stumbles on this post:
  exec { "test1": command => "/bin/false", unless => "/bin/true" }  # unless = only if this fails
  notify { "false, unless true fails, which it wont: this should not fail (notrun) and i should see this": require => Exec["test1"] }
  exec { "test2": command => "/bin/false", onlyif => "/bin/true" }   # onlyif = only if this returns true
  notify { "false, but only if true: this should fail and i should not see this": require => Exec["test2"] }
  exec { "test3": command => "/bin/true", unless => "/bin/true" } # unless = only if this fails
  notify { "true, unless true fails, which it wont: this should not run true (notrun) and i should see this": require => Exec["test3"] }
  exec { "test4": command => "/bin/true", onlyif => "/bin/false" } # onlyif = only if this returns true
  notify { "true, but only if false returns true, which it wont: true will be run and i should see this": require => Exec["test4"] }


R.I.Pienaar

unread,
Feb 15, 2018, 5:54:47 AM2/15/18
to puppet...@googlegroups.com


On Thu, 15 Feb 2018, at 11:41, buoyant_puppy wrote:
> I think I got this. My main issue was the 'true' logic with an 'onlyif',
> because that's always only going to either run (= and therefore meet the
> requirement) or not run at all (= which also meets the requirement since
> it's not a failure).
>
> I feel the choice of words here leaves room for confusion. Like "unless"...
> unless succeeds? unless fails? "requires" also leaves some amgiuity as

"unless this thing is true" seems clear to me, also in line with how ruby works and also puppet

if $thing { }
unless $thing { }


> well, since it considers the requirement met as long as the required
> resource did not explicitly return a failure. So "notrun" is just as good
> as success, which to me doesn't really intuitively match what I think
> "require" means.

require means the required resource is in the desired start. Your desired state is not to run at certain times, the desired behavior was reached so the resource is in pass state. require is a generic meta param that applies to all resources - it does not know the particulars of what you think a certain resource is doing, its at a higher level.

>
> Here's a set of tests that illustrate all this more clearly, in case it
> helps someone else that stumbles on this post:
> exec { "test1": command => "/bin/false", unless => "/bin/true" } #
> unless = only if this fails
> notify { "false, unless true fails, which it wont: this should not fail
> (notrun) and i should see this": require => Exec["test1"] }
> exec { "test2": command => "/bin/false", onlyif => "/bin/true" } #
> onlyif = only if this returns true
> notify { "false, but only if true: this should fail and i should not see
> this": require => Exec["test2"] }
> exec { "test3": command => "/bin/true", unless => "/bin/true" } # unless
> = only if this fails
> notify { "true, unless true fails, which it wont: this should not run
> true (notrun) and i should see this": require => Exec["test3"] }
> exec { "test4": command => "/bin/true", onlyif => "/bin/false" } # onlyif
> = only if this returns true
> notify { "true, but only if false returns true, which it wont: true will
> be run and i should see this": require => Exec["test4"] }
>
>
> --
> You received this message because you are subscribed to the Google
> Groups "Puppet Users" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to puppet-users...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/puppet-users/e9c2a7a4-148b-4337-aba7-acf308e7cbe0%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.


--
R.I.Pienaar / www.devco.net / @ripienaar

jcbollinger

unread,
Feb 15, 2018, 9:17:20 AM2/15/18
to Puppet Users


On Thursday, February 15, 2018 at 4:41:59 AM UTC-6, buoyant_puppy wrote:
I think I got this. My main issue was the 'true' logic with an 'onlyif', because that's always only going to either run (= and therefore meet the requirement) or not run at all (= which also meets the requirement since it's not a failure).



Yes, I think that covers it.

 
I feel the choice of words here leaves room for confusion. Like "unless"... unless succeeds? unless fails? "requires" also leaves some amgiuity as well, since it considers the requirement met as long as the required resource did not explicitly return a failure. So "notrun" is just as good as success, which to me doesn't really intuitively match what I think "require" means.



This has been a point of confusion with the Exec resource type for the whole nine-ish years that I have been involved with Puppet.  Maybe it's time to actually file an issue against the docs to get it cleaned up.

But I don't think it's an issue with the metaparameter names.  Rather, it's a problem with the overall characterization of an Exec resource, which is not well addressed by the current docs.  I most recently answered essentially this same question over at StackOverflow.  Here's the heart of it:

Like any other resource, Execs model target-machine state, though in their case, that state is local to the context of one catalog run. Often it is described as whether the Exec's command has been run or not, but it is better characterized the other way around, as whether the Exec's command needs to be run or not. If it is in the "needs to be run" state then successfully executing the Exec's command transitions it to the "does not need to be run" state.


The unlessonlyif, and creates properties of an Exec serve to determine the initial state of the corresponding physical (so to speak) resource. If none of them are provided then the physical resource is initially in the "needs to be run" state. If one or more of them is provided then they may indicate that the Exec initially is in the "does not need to be run" state. And that's the target state. In that case, then, the Exec is successfully applied without running its command.


I've given substantially the same answer before in this group, too.


John

jcbollinger

unread,
Feb 15, 2018, 10:13:15 AM2/15/18
to Puppet Users


On Thursday, February 15, 2018 at 8:17:20 AM UTC-6, jcbollinger wrote:
This has been a point of confusion with the Exec resource type for the whole nine-ish years that I have been involved with Puppet.  Maybe it's time to actually file an issue against the docs to get it cleaned up.




John

buoyant_puppy

unread,
Feb 15, 2018, 10:46:17 AM2/15/18
to Puppet Users
Got it, thanks everyone.

Just one small point to add - I'm not actually directly concerned with Execs here. If you look at my original example, I was needing to do a conditional check like "if directory exists then...", and my Exec-based solution for it is just an ugly workaround. I understand the puppet philosophy here is focused on being declarative, but it's just extremely common that we don't have the pleasure of working in a purely declarative environment. As such I think it'd be nice to see unless/requires/etc evolve further.


jcbollinger

unread,
Feb 16, 2018, 11:44:16 AM2/16/18
to Puppet Users


On Thursday, February 15, 2018 at 9:46:17 AM UTC-6, buoyant_puppy wrote:
Got it, thanks everyone.

Just one small point to add - I'm not actually directly concerned with Execs here. If you look at my original example, I was needing to do a conditional check like "if directory exists then...", and my Exec-based solution for it is just an ugly workaround. I understand the puppet philosophy here is focused on being declarative, but it's just extremely common that we don't have the pleasure of working in a purely declarative environment. As such I think it'd be nice to see unless/requires/etc evolve further.


You are not the first to express an interest in Puppet developing in that direction, but Puppet already has mechanisms for the kind of thing you describe.  The main approaches to adapting to target-machine state are
  1. to rely on facts collected from the node to influence details of the catalog.  To this end, there are well-developed facilities for defining and distributing your own custom facts.
  2. to rely on resource providers to behave appropriately for the target environment; this is under the control of provider developers, including you if you wish to be one.
These are well-matched to Puppet's model of operation, which is to first compute a target state based on the machine's identity and current state, site manifests, and site data (catalog building); then to attempt to take whatever action is needed to put the machine in that state (catalog application).  A key aspect here is that the target state embodied by a catalog is unconditional at the level of abstraction of the catalog, and perhaps that's what you mean by "purely declarative".  But although that perhaps fits the catalog, it does not fit Puppet DSL at all, nor, therefore, the overall system.

In the past, I have been fond of saying "Puppet is not a script engine."  I consider that a strength, not a weakness.


John

Reply all
Reply to author
Forward
0 new messages