Question

I am using puppet to read a fact from facter, and based on that I apply a different configuration to my modules.

Problem:

the puppet agent isn't seeing this fact. Running puppet agent --test interactively works as expected. Even running it non-interactively from a script seems to work fine. Only the agent itself is screwing up.

Process:

I am deploying an Ubuntu-based app stack on EC2. Using userdata (#cloud-config), I set an environment variable in /etc/environment:

export FACTER_tl_role=development

then immediately in #cloud-config, i source /etc/environment. only THEN i apt-get install puppet (i moved away from using package: puppet to eliminate ambiguity in the sequence of #cloud-config steps)

Once the instance boots, I confirm that the fact is available: running facter tl_role returns "development". I then check /var/log/syslog, and apparently the puppet agent is not seeing this fact - I know this because it's unable to compile the catalog, and there's nothing (blank) where I'm supposed to be seeing the value of the variable set depending on this fact.

However, running puppet agent --test interactively compiles and runs the catalog just fine. even running this from the #cloud-config script (immediately after installing puppet) also works just fine.

How do I make this fact available to the puppet agent? Restarting the agent service makes no difference, it remains unaware of the custom fact. Rebooting the instance also makes no difference.

here's some code:

EC2 userdata:

#cloud-config

puppet:
  conf:
    agent:
      server: "puppet.foo.bar"
      certname: "%i.%f"
      report: "true"

runcmd:
- sleep 20
- echo 'export FACTER_tl_role=development' >> /etc/environment
- . /etc/environment
- apt-get install puppet
- puppet agent --test

Main puppet manifest:

# /etc/puppet/manifests/site.pp
node default {
case $tl_role {
    'development':  { $sitedomain = "dev.foo.bar"}
    'production':   { $sitedomain = "new.foo.bar"}
}
class {"code" : sitedomain => $sitedomain}
class {"apache::site" : sitedomain => $sitedomain}
class {"nodejs::grunt-daemon" : sitedomain => $sitedomain}

And then I see failures where $sitedomain is supposed to be, so $tl_role appears to be not set.

Any ideas? This is exploding my brain....

Was it helpful?

Solution

Another easy option would be to drop a fact into an external fact.

Dropping a file into /etc/facter/facts.d/* is fairly easy, and you can use a text file, yaml json or an executable to do it.

http://docs.puppetlabs.com/guides/custom_facts.html#external-facts

*that's on Open source puppet, on unix-y machines. See the link for the full docs.

OTHER TIPS

Thank you, @christopher. This may be a good solution, I will test it and possibly move to it from my current horrible hack. The answer I got in the Puppet Users Google Group was that I should not assume that the Puppet agent process will have an environment of a login shell, and that Facter will also have this environment when it is run by the Puppet agent.

Here is the way I solved it (admittedly, by brute force):

runcmd:
- echo 'export FACTER_tl_role=development' >> /etc/environment
- . /etc/environment
- apt-get install puppet
- service puppet stop
- sed -i '/init-functions/a\. \/etc\/environment' /etc/init.d/puppet
- puppet agent --test
- service puppet start

As you can see, after installing Puppet, I stop the agent, and add a line to /etc/init.d/puppet to source /etc/environment. Then I start the agent. NOT ideal... but it works!

I don't think . /etc/environment is going to work properly the way cloud-init executes runcmd. Two possible solutions:

  • Export the variable with the puppet agent command:

    export FACTER_tl_role=development && puppet agent --test

If that doesn't work:

  • Just drop the commands into a user-data script and wire them together as a "multipart input" (described in the cloud-init docs).

The second solution executes the commands as a proper shell script, and would likely fix the problem. If the first works, though, it's easier to do with what you have.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top