octocatalog-diff icon indicating copy to clipboard operation
octocatalog-diff copied to clipboard

json --fact-file data straight from puppetdb fails

Open elfchief opened this issue 4 years ago • 0 comments

Description

When octocatalog-diff (version 2.1.0) is provided a set of facts via --facts-file, it will fail if that file contains a json array straight out of puppetdb. Being able to use facts straight from puppetdb like this is useful for (e.g.) providing simple offline caching of facts.

For example:

$ curl -s http://puppetdb/pdb/query/v4/nodes/somehost.internal/facts > /tmp/somehost_facts.json
$ jq . /tmp/somehost_facts.json  | head
[
  {
    "certname": "somehost.internal",
    "environment": "production",
    "name": "id",
    "value": "root"
  },
  (etc)

and then:

$ octocatalog-diff --hostname somehost.internal --fact-file /tmp/somehost_facts.json
Traceback (most recent call last):
	17: from /opt/puppetlabs/puppet/bin/octocatalog-diff:23:in `<main>'
	16: from /opt/puppetlabs/puppet/bin/octocatalog-diff:23:in `load'
	15: from /opt/puppetlabs/puppet/lib/ruby/gems/2.7.0/gems/octocatalog-diff-2.1.0/bin/octocatalog-diff:34:in `<top (required)>'
	14: from /opt/puppetlabs/puppet/lib/ruby/gems/2.7.0/gems/octocatalog-diff-2.1.0/lib/octocatalog-diff/cli.rb:69:in `cli'
	13: from /opt/puppetlabs/puppet/lib/ruby/gems/2.7.0/gems/octocatalog-diff-2.1.0/lib/octocatalog-diff/cli.rb:168:in `parse_opts'
	12: from /opt/puppetlabs/puppet/lib/ruby/gems/2.7.0/gems/octocatalog-diff-2.1.0/lib/octocatalog-diff/cli/options.rb:66:in `parse_options'
	11: from /opt/puppetlabs/puppet/lib/ruby/2.7.0/optparse.rb:1691:in `parse!'
	10: from /opt/puppetlabs/puppet/lib/ruby/2.7.0/optparse.rb:1666:in `permute!'
	 9: from /opt/puppetlabs/puppet/lib/ruby/2.7.0/optparse.rb:1569:in `order!'
	 8: from /opt/puppetlabs/puppet/lib/ruby/2.7.0/optparse.rb:1575:in `parse_in_order'
	 7: from /opt/puppetlabs/puppet/lib/ruby/2.7.0/optparse.rb:1575:in `catch'
	 6: from /opt/puppetlabs/puppet/lib/ruby/2.7.0/optparse.rb:1589:in `block in parse_in_order'
	 5: from /opt/puppetlabs/puppet/lib/ruby/gems/2.7.0/gems/octocatalog-diff-2.1.0/lib/octocatalog-diff/cli/options.rb:128:in `block in option_globally_or_per_branch_string'
	 4: from /opt/puppetlabs/puppet/lib/ruby/gems/2.7.0/gems/octocatalog-diff-2.1.0/lib/octocatalog-diff/cli/options.rb:238:in `translate_option'
	 3: from /opt/puppetlabs/puppet/lib/ruby/gems/2.7.0/gems/octocatalog-diff-2.1.0/lib/octocatalog-diff/cli/options/fact_file.rb:23:in `block in parse'
	 2: from /opt/puppetlabs/puppet/lib/ruby/gems/2.7.0/gems/octocatalog-diff-2.1.0/lib/octocatalog-diff/cli/options/fact_file.rb:23:in `new'
	 1: from /opt/puppetlabs/puppet/lib/ruby/gems/2.7.0/gems/octocatalog-diff-2.1.0/lib/octocatalog-diff/facts.rb:27:in `initialize'
/opt/puppetlabs/puppet/lib/ruby/gems/2.7.0/gems/octocatalog-diff-2.1.0/lib/octocatalog-diff/facts/json.rb:18:in `fact_retriever': undefined method `keys' for #<Array:0x00000000024a04c8> (NoMethodError)

Possible Fix

One possible fix would be to add something similar to the following immediately after the JSON::parse call in self.fact_retriever, inside facts/json.rb:

        if facts.is_a?(Array) && facts[0].is_a?(Hash) && facts[0].keys.include?('certname')
            # you probably gave us the raw puppetdb output
            fixed_facts = {}
            facts.map { |x| fixed_facts[x['name']] = x['value'] }
            facts = fixed_facts
        end

This works, and allows catalogs to be built using that straight-from-puppetdb json goodness.

I am not submitting this as a pull request because 1-- I don't really know ruby but the above feels a bit sloppy to me and I suspect there might be a more ruby-like way to handle this, and 2-- getting myself a test environment that can actually run and pass the entire octocatalog-diff unit test suite has been... challenging. I'll be happy to submit the above as a PR if that is your desire, though.

Environment

Although it is unlikely to matter in this specific case:

  • OS: CentOS Linux release 8.2.2004
  • Ruby version: ruby 2.7.3p183 (2021-04-05 revision 6847ee089d) [x86_64-linux] (the bundled ruby from the puppet agent)
  • Puppet version: puppet-agent-7.10.0-1.el8.x86_64 (official PuppetLabs puppet-agent RPM)
  • octocatalog-diff version: octocatalog-diff 2.1.0

elfchief avatar Aug 30 '21 20:08 elfchief