1

How can I make the below logic work? My aim is to compare the value of custom fact $environment and the content of the file /etc/facter/facts.d/oldvalue.

If the custom fact $environment is not equal to the content of file /etc/facter/facts.d/oldvalue, then execute the following code.

exec {'catenvchange' :
   command => "/bin/cat /root/oldvalue"}

if $environment != exec['catenvchange'] {#code#}
Kevin M
  • 45
  • 1
  • 8

1 Answers1

2

Exec resources do not work that way. In fact, no resource works that way, or any way remotely like that. Moreover, the directory /etc/facter/facts.d/ serves a special purpose, and your expectation for how it might be appropriate to use a file within is not consistent with that purpose.

What you describe wanting to do looks vaguely like setting up an external fact and testing its value. If you drop an executable script named /etc/facter/facts.d/anything by some means (manually, plugin sync, File resource, ...) then that script will be executed before each Puppet run as part of the process of gathering node facts. The standard output generated by the script would be parsed for key=value pairs, each defining a fact name and its value. The facts so designated, such as one named "last_environment" will be available during catalog building. You could then use it like so:

if $::environment != $::last_environment {
    # ...
}

Update:

One way to use this mechanism to memorialize the value that a given fact, say $::environment, has on one run so that it can be read back on the next run would be to declare a File resource managing an external fact script. For example,

file { '/etc/facter/facts.d/oldvalues':
  ensure  => 'file',
  owner   => 'root',
  group   => 'root',
  mode    => '0755',
  content => "#!/bin/bash\necho 'last_environment=${::environment}'\n"
}
John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • I changed the file location. Basically, I want to store the contents of /etc/facter/facts.d/facts.yaml to the file /root/oldvalue as I am trying to track changes to facts. Since facts run first before executing modules, it takes 2 puppet runs for the facts to be set right and execute my code based on changed facts. – Kevin M Sep 04 '15 at 18:49
  • Information gathered from the target node is available to the catalog builder only in the form of facts. If it so happens that the target node is also the machine on which the catalog builder is running, however, (i.e. for `puppet apply`) then it may serve your purpose to use the `generate()` function to run a command on the catalog building machine and collect its output. Under no circumstances, however, is any result of applying a resource available during the process of building the catalog containing that resource. – John Bollinger Sep 04 '15 at 18:55
  • I have the following under /etc/facter/facts.d cat oldvalue #!/bin/bash oldvalue="`cat /etc/facter/facts.d/facts.yaml | grep environment | awk '{print $2}'`"; printf $oldvalue; I am still not able to use the fact $::oldvalue. During the puppet run it comes out as Fact file /etc/facter/facts.d/oldvalue was parsed but returned an empty data set – Kevin M Sep 04 '15 at 19:17
  • What does `facter --version` tell you? – John Bollinger Sep 04 '15 at 19:18
  • facter --version 2.4.1 – Kevin M Sep 04 '15 at 19:53
  • Sorry, my bad. The script must emit the fact data in `key=value` form. Also, be sure its executable bit is set. Here are the relevant docs: https://docs.puppetlabs.com/facter/2.4/custom_facts.html. – John Bollinger Sep 04 '15 at 19:58
  • I tried this and it doesn't serve my purpose. All I want to do is query a field in my MySQL database to see if the that field changed. If it changed, execute a different set of code. Since I am pushing out that field in my database as a fact, I am not able to make changes as and when the database changes. – Kevin M Sep 04 '15 at 20:42
  • I don't see what prevents you from using an external fact to memorialize the value that another fact had at the time of the previous catalog run. Of course, you can also write a Ruby custom fact that works with you memorializing the old value any other way you choose. The key point here is that if you want to store data on the target node and make it available to the catalog builder running on a puppet master, then your *only* mechanism for communicating that data to the master is via a fact. – John Bollinger Sep 04 '15 at 20:56
  • external fact? how? Say there is a fact named $environment, How do I use an external fact to memorialize the value of $environment from the previous run and use it in the current run? – Kevin M Sep 04 '15 at 21:02
  • External facts are what we have already been talking about. I corrected my answer, and updated it with an example of one way that the value of the `$::environment` fact could be memorialized for read-back during the subsequent puppet run. – John Bollinger Sep 04 '15 at 21:16
  • John, Awesome! Solved all my problems. Thank you and have a good long weekend. – Kevin M Sep 04 '15 at 21:40