0

My requirement is this:

  1. Look for changes in the file /tmp/file
  2. If there is a change, execute these in the following order:
    • run command3
    • run command2
    • run command1
  3. If there is NO change in the file /tmp/file, do nothing.

My code is like this:

exec { 'exec3':
  command => 'command3',
  require => File['file'],
}

exec { 'exec2':
  command => 'command2',
  require => Exec['exec3'],
}

exec { 'exec1':
  command     => 'command1',
  require     => Exec['exec2'],
  subscribe   => File['file'],
  refreshonly => true,
}

But, whether there is a change to /tmp/file or not, command3 and command2 always runs. How do I prevent it? I do not want "require" to be run in exec1 when there is no change to /tmp/file.

Alex Harvey
  • 14,494
  • 5
  • 61
  • 97
Hem
  • 619
  • 13
  • 26

1 Answers1

5

You need: firstly, for all of the execs to subscribe to the file resource; secondly, for each of those to also require their preceding exec resources; and thirdly, for each exec to be set to refreshonly.

Here is some code that does that:

file { 'file':
  ensure  => file,
  path    => '/tmp/file',
  content => "some content\n",
}

exec { 'exec1':
  command   => 'command1', 
  subscribe => File['file'],
  refreshonly => true,
}

exec { 'exec2':
  command   => 'command2',
  subscribe => File['file'],
  require   => Exec['exec1'],
  refreshonly => true,
} 

exec { 'exec3':
  command   => 'command3',
  subscribe => File['file'],
  require   => Exec['exec2'],
  refreshonly => true,
}

How this works:

  • Using exec's refreshonly mechanism, exec1 is triggered only on refresh events, and a refresh event is sent if and only if there is a change in file1's content.

  • All of the exec events need to be similarly triggered by the changes in the file's content, thus they all subscribe to the file.

  • But the execs need to be ordered in a specific way, and thus exec2 requires exec1, and exec3 requires exec2.

See also reasons why refreshonly needs to be used carefully.

Alex Harvey
  • 14,494
  • 5
  • 61
  • 97
  • 1
    It is perhaps worth noting that unlike anything else in Puppet, resource defaults have dynamic scope. That has no particular impact on this answer itself, but it could produce unexpected results when this code is inserted into the OP's context. – John Bollinger Nov 06 '17 at 20:01
  • @Alex Harvey, thank you. It worked. Still a question though, In my code, can you explain me why commands in all exec blocks run when the first exec block supposed to run only when there is a change to the file. – Hem Nov 06 '17 at 22:23
  • 1
    The `require` metaparameter declares only the order in which things occur, all other things being equal (and also prevents the second resource from being applied at all if the first one fails to apply). Meanwhile, the `subscribe` metaparameter i conjunction with `refreshonly => true` declares that the resource should be applied if and only if the resource subscribed to changes state. Yes, it's a little confusing at first. – Alex Harvey Nov 07 '17 at 00:24