arrow-down coffee engineering consultancy development remote-management support linkedin twitter youtube email phone

First impressions of the new cfacter

Submitted by Walter Heck on September 29, 2014

Having just come back from PuppetConf 2014 in the San Francisco last week, there have been a lot of new developments. Some of the most significant changes since Puppet was started all the way 10 years back have been announced.

A lot of the announced changes have to do with a move away from Ruby as the language for everything puppet. We have already seen this started when PuppetDB was implemented in Clojure. That has been largely succesful and without pain, so there's good hope we can extend that into the rest of the toolset.

The first two tools we can see moving away from Ruby can already be tried today: cfacter and puppetserver. I got down and dirty with cfacter and here are my initial findings:

cfacter

First up I took a look at cfacter. Right now we're in very early release stages, so you have to build it manually, which is always a pain. I tried building on a clean Ubuntu 14.04 machine with puppetserver running without too many issues, following the instructions. Even with my extremely limited C++ knowledge this went without a glitch. 

Execution time

One of the first things I was interested in was execution time, as this is cited to be one of the main drivers to do this. I was not disappointed:


root@cobalt:~# time facter > /dev/null
real 0m3.830s
user 0m0.593s
sys 0m0.913s

root@cobalt:~# time ./cfacter/release/bin/cfacter > /dev/null
real 0m0.358s
user 0m0.220s
sys 0m0.103s

That is a lot of speed improvement (10.7 times to be exact)! This might not seem too significant, but it is when you think of an environment running the agent  every half an hour across hundreds or thousands of machines. This is all time that those machines can now spend on other stuff then just facter. It also means the time it takes to do a puppet agent run will come down, as facter is executed as part of that.

Debug messages

Debugging properly has been an issue for a long time with facter. Particularly running facter in --debug mode would show little of what was going on. No more! Here's some debug output from both to compare:

Here's old-school facter:


value for network_ip6tnl0 is still nil
value for network_ip_vti0 is still nil
value for network_sit0 is still nil
value for network_teql0 is still nil
value for network_tunl0 is still nil
Found no suitable resolves of 2 for swapencrypted
value for swapencrypted is still nil
Found no suitable resolves of 1 for ec2_metadata
value for ec2_metadata is still nil
Found no suitable resolves of 1 for ec2_userdata
value for ec2_userdata is still nil
Found no suitable resolves of 2 for iphostnumber
value for iphostnumber is still nil

That doesn't tell me anything! Unless you happen to be a/the facter developer, this is basically useless.


root@cobalt:~/cfacter/release/bin# ./cfacter --debug
  2014-09-28 22:21:45.603598 INFO  puppetlabs.facter.main - executed with command line: --debug.
  2014-09-28 22:21:45.604366 DEBUG puppetlabs.facter.ruby - searching "/usr/lib" for ruby libraries.
  2014-09-28 22:21:45.604775 DEBUG puppetlabs.facter.ruby - found candidate ruby library /usr/lib/libruby-1.9.1.so.1.9.1.
  2014-09-28 22:21:45.605693 INFO  puppetlabs.facter.ruby - ruby loaded from "/usr/lib/libruby-1.9.1.so.1.9.1".
  2014-09-28 22:21:45.605784 DEBUG puppetlabs.facter.util.posix.dynamic_library - symbol rb_funcallv not found in library /usr/lib/libruby-1.9.1.so.1.9.1, trying alias rb_funcall2.
  2014-09-28 22:21:45.605859 DEBUG puppetlabs.facter.util.posix.dynamic_library - symbol rb_float_new_in_heap not found in library /usr/lib/libruby-1.9.1.so.1.9.1, trying alias rb_float_new.
  2014-09-28 22:21:45.605916 DEBUG puppetlabs.facter.util.posix.dynamic_library - symbol rb_ary_new_capa not found in library /usr/lib/libruby-1.9.1.so.1.9.1, trying alias rb_ary_new2.
  2014-09-28 22:21:45.605986 DEBUG puppetlabs.facter.util.posix.dynamic_library - symbol ruby_setup not found in library /usr/lib/libruby-1.9.1.so.1.9.1.
  2014-09-28 22:21:45.610042 INFO  puppetlabs.facter.ruby - using ruby version 1.9.3 to resolve custom facts.
  2014-09-28 22:21:45.618980 INFO  puppetlabs.facter.main - resolving all facts.
  2014-09-28 22:21:45.619069 DEBUG puppetlabs.facter.facts.collection - fact "cfacterversion" has resolved to "0.2.0".
  2014-09-28 22:21:45.619113 DEBUG puppetlabs.facter.facts.collection - fact "facterversion" has resolved to "0.2.0".
  2014-09-28 22:21:45.619310 DEBUG puppetlabs.facter.facts.collection - skipping external facts for "/etc/facter/facts.d": No such file or directory
  2014-09-28 22:21:45.619354 DEBUG puppetlabs.facter.facts.collection - skipping external facts for "/etc/puppetlabs/facter/facts.d": No such file or directory
  2014-09-28 22:21:45.619381 DEBUG puppetlabs.facter.facts.collection - no external facts were found.
  2014-09-28 22:21:45.619717 DEBUG puppetlabs.facter.ruby - loading all custom facts.
  2014-09-28 22:21:45.619779 DEBUG puppetlabs.facter.facts.resolver - resolving kernel facts.
  2014-09-28 22:21:45.619830 DEBUG puppetlabs.facter.facts.collection - fact "kernel" has resolved to "Linux".
  2014-09-28 22:21:45.619871 DEBUG puppetlabs.facter.facts.collection - fact "kernelrelease" has resolved to "3.15.4-x86_64-linode45".
  2014-09-28 22:21:45.619924 DEBUG puppetlabs.facter.facts.collection - fact "kernelversion" has resolved to "3.15.4".
  2014-09-28 22:21:45.619967 DEBUG puppetlabs.facter.facts.collection - fact "kernelmajversion" has resolved to "3.15".
  2014-09-28 22:21:45.620007 DEBUG puppetlabs.facter.facts.resolver - resolving operating system facts.
  2014-09-28 22:21:45.620046 DEBUG puppetlabs.facter.facts.resolver - resolving Linux Standard Base facts.
  2014-09-28 22:21:45.620115 DEBUG puppetlabs.facter.execution - executing command: /usr/bin/lsb_release -i -s
  2014-09-28 22:21:45.669448 DEBUG | - Ubuntu
  2014-09-28 22:21:45.669568 DEBUG puppetlabs.facter.execution - process exited with status code 0.
  2014-09-28 22:21:45.669654 DEBUG puppetlabs.facter.facts.collection - fact "lsbdistid" has resolved to "Ubuntu".
  2014-09-28 22:21:45.669710 DEBUG puppetlabs.facter.execution - executing command: /usr/bin/lsb_release -r -s
  2014-09-28 22:21:45.720320 DEBUG | - 14.04

That looks great! I can actually see what's happening and why, yay!

Fact values

This is where it gets a bit more tricky. I wanted to see what the differences were between facts returned by facter, and those by cfacter. To this end, I executed a simple test:


facter > facter.txt && ./cfacter > cfacter.txt

I then ran a diff on the resulting two files. 


diff -u cfacter.txt facter.txt
--- cfacter.txt 2014-09-28 22:30:30.567496574 +0000
+++ facter.txt  2014-09-28 22:30:30.207508905 +0000

Here are some of the things I noticed:

  1. Some facts changed value
    
    -macaddress => f2:3c:91:56:53:d9
    +macaddress => 66:2c:0e:85:17:6e

    What now?! Turns out the reported mac address changes from the very first interface encountered to the first connected network link:

    
    root@cobalt:~# ip link show dummy0
    2: dummy0: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN mode DEFAULT group default
        link/ether 66:2c:0e:85:17:6e brd ff:ff:ff:ff:ff:ff
    root@cobalt:~# ip link show eth0
    3: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
        link/ether f2:3c:91:56:53:d9 brd ff:ff:ff:ff:ff:ff

    This actually looks like it fixed a bug, but I can still imagine this causing a problem or two for people who are unaware.

  2. Some facts are new: mountpoints, partitions, cfacterversion, dhcpservers. These all look very useful.
  3. Some facts have disappeared: puppetversion (bug?), rubyversion (duh, we're in c++ now) and path for instance
  4. Some structured facts come out in a differently ordered hash. This is not a problem as far as I can tell.

Conclusion

The initial findings look good. Of course the bug database is still very small but it's growing quite fast since the announcement last week at PuppetConf 2014. I have a bigger concern though: the number of people familiar enough with C++ to contribute seems to be a lot smaller then the number of people with Ruby skills. By fragmenting the languages in which different parts of puppet are written, there's a risk of making it much harder for people to contribute to Puppet across the toolset.

We can just hope that this doesn't mean that open source contributions will be any lower. This can only be seen in time.