Ask Your Question

Unless conditional statement not working [closed]

asked 2015-06-22 16:54:48 -0600

DX gravatar image

I installed several applications using exec, include and class. Then when puppet agent runs every certain amount of time it installs them again. To avoid this I created a file in a directory every time I installed an application, so if the file exists it doesn't get installed again. It works for the installations where I use exec using the onlyif clause. For the instances where I use include or class I tried the unless conditional statement but is not working for me. Can someone please let me know what am I doing wrong or another way to make sure the installations only occur once? I am new to puppet and not familiar with custom facts. Here is a code with class:

unless '/usr/bin/test -e /etc/puppet/done/rabbitmq' {
    notify {"File does not exist":}

    class { '::rabbitmq':
    port              => '5672',
    service_manage    => true,
    package_gpg_key   => '/etc/pki/rpm-gpg/GPG-KEY-rabbitmq',
    package_provider  => 'yum',
    config            => '/etc/puppet/modules/aspen/templates/rabbitmq.config.erb'

    file {"/etc/puppet/done/rabbitmq":
            content => "rabbitmq installation completed in Aspen1 \r\n",

and here is with include:

unless '/usr/bin/test -e /etc/puppet/done/supervisord1' {
    include aspen::bootstrapsupervisor
    file {"/etc/puppet/done/supervisord1":
        content => "supervisord installation completed in Aspen1 \r\n",

I don't get any error codes, but the unless statement doesn't work.

edit retag flag offensive reopen merge delete

Closed for the following reason the question is answered, right answer was accepted by DX
close date 2015-06-25 13:03:19.594194

1 Answer

Sort by ยป oldest newest most voted

answered 2015-06-23 11:54:50 -0600

Jeremiah Powell gravatar image

Puppet will never run /usr/bin/test in the example. Puppet DSL is not a scripting language but a declarative language.

The string '/usr/bin/test -e /etc/puppet/done/supervisord1' is just a string. Empty strings evaluate to false while strings containing text evaluate to true.

So unless '/usr/bin/test -e /etc/puppet/done/supervisord1' {...} is equivalent to unless true {...}.

The conditional unless has the opposite meaning of if. Unless will only run the associated block if the condition is false. So the code in the block will never be run.

Unless, if, class names, setting variables, running functions and resolving definitions happen a compile time, usually on a Master. Obtaining facts, executing resources and reporting results happen at run-time on an agent.

If the purpose of this code is to determine a property of an agent then there are only three methods of using this at compile time.

  1. Function running on the Puppet Master
  2. Fact running on the Puppet agent
  3. Exec special attributes running on the Puppet agent

Functions are called by the master only at compile time. The agent never sees any functions.

If a file is being created on the master then a Ruby function can be written and called to check for this file on the master. This also works in master-less setups since every agent is also its own master in that model.

Functions are Ruby code. Ruby code is added and updated by agents during Puppet runs. So the custom function is only available after the Master runs its agent once the code is published to the Master.

If a file is being created on the agent then a custom fact can be written to check for the file. This means that the information on the file will only be available on the next Puppet agent run after the file exists. This also means that you have to write Ruby code to test for the file.

Lastly the special Exec resource has agent-run-time only attributes as you have seen. These can run arbitrary system commands during the agent run to block the operation of the exec.

As an aside, Exec resources are considered poor form. Use of Exec moves the control from the master to the agent. Their command attributes can contain side-effects.

Unfortunately the alternative to an exec resource is to re-write the simple exec into a native type and provider. Writing native types and providers involves Ruby programming much more complicated than a short fact script or small function definition.

edit flag offensive delete link more


Thank you for the explanation! I suspected it was taking the '/usr/bin/test...' as a string instead of evaluating it. I guess a solution would be to use a custom fact to evaluate if the file exists, then the unless statement should work. Not familiar with them but always wiling to learn.

DX gravatar imageDX ( 2015-06-23 14:15:38 -0600 )edit

Question Tools

1 follower


Asked: 2015-06-22 16:54:48 -0600

Seen: 897 times

Last updated: Jun 23 '15