0

I have seen the documentation, especially External Facts and Custom Facts.

I have the following yum_repos.rb:

require 'facter'
Facter.add('yum_repos') do
    setcode '/usr/bin/python3 /opt/puppetlabs/puppet/cache/lib/facter/yum_repos.py'
end

I have the following yum_repos.py:

#!/usr/bin/python3
import configparser
import os
import json

result_dict={}
yum_repos_dir = '/etc/yum.repos.d'
for yum_repo_file in os.listdir(yum_repos_dir):
    if not yum_repo_file.endswith(".repo"):
        continue
    yum_repo_name=yum_repo_file.replace(".repo","")
    config = configparser.ConfigParser()
    config.read(os.path.join(yum_repos_dir, yum_repo_file))
    result_dict[yum_repo_name] = {}
    for section in config.sections():
        result_dict[yum_repo_name][section] = dict(config[section])
print(json.dumps(result_dict))

When I check facter, it all runs, but the yum_repos fact is a string. Why isn't it structured? I found somewhere on the internet, saying (for old versions of puppet) that stringify_facts must be set to false, so I tried that, but the behavior did not change. I believe that the default was changed in 4.0 to not stringify.

I am using puppet 6.24.0

I try to access the facts in a puppet class like this:

if $facts['yum_repos']['redhat']...['enabled'] != 1 {
    ...
}

And when I run puppet agent, I get the error message:

Error: Could not retrieve catalog from remote server: Error 500 on SERVER: Server Error: Evaluation Error: A substring operation does not accept a String as a character index. Expected an Integer
Edward Ned Harvey
  • 6,525
  • 5
  • 36
  • 45

1 Answers1

0

I never figured out why puppet is stringifying the fact, but I was able to workaround by explicitly calling parsejson(), like so:

if parsejson($facts['yum_repos'])['redhat']...['enabled'] != "1" {
    ...
}
Edward Ned Harvey
  • 6,525
  • 5
  • 36
  • 45
  • If you create a fact that obtains its value directly from the output of a system command, then how would that *not* come in as a string? – John Bollinger Aug 12 '21 at 13:13
  • @JohnBollinger All the puppet/facter documentation referenced above says if you output json, yaml, or certain other structured formats, then it is parsed automatically by facter into structured data. Except in old versions of puppet (<4.0) where that feature was not enabled by default and needed to be enabled in puppet.conf. After 4.0, it's enabled by default. – Edward Ned Harvey Aug 13 '21 at 13:00
  • I see. Well, either the docs where you saw that where unclear about their scope, or you overlooked it: that applies to [*external* facts](https://puppet.com/docs/puppet/7/external_facts.html), not [custom facts implemented via the Ruby API](https://puppet.com/docs/puppet/7/fact_overview.html). – John Bollinger Aug 13 '21 at 13:34