Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Factset instructions appear unsupported for Puppet 2021.4.x #321

Open
chambersmp opened this issue Jan 24, 2022 · 1 comment
Open

Factset instructions appear unsupported for Puppet 2021.4.x #321

chambersmp opened this issue Jan 24, 2022 · 1 comment

Comments

@chambersmp
Copy link
Contributor

chambersmp commented Jan 24, 2022

Issue

The instructions to generate a node's factset on the Puppet primary server do not seem to work for Puppet Enterprise version 2021.4.x.

Provided Example:
puppet facts --terminus puppetdb <node certname> > fact_set_name.json

This command results in an empty factset containing only the node's certname as a key with null value.

Recommendation

  1. Add the following factset alternatives to README documentation:

Puppet Query CLI from PE Primary Server
puppet query "inventory { certname = '<targetnode>' }"

curl from PE Primary Server
curl -X GET http://localhost:8080/pdb/query/v4/inventory -d 'query=["=", "certname", "<targetnode>"]'

Authenticated PuppetDB Query from Remote Client
curl -X GET https://<pe-primary-fqdn>:8081/pdb/query/v4/inventory?query=["=", "certname", "<targetnode>"]
-H 'X-Authentication: <Token>"

The resultant factset output requires a minor edit to change the 'facts' key to 'values' to allow onceover processing. The next recommendation suggests updating the onceover > control-repo class to accept the facts key as an alternative to avoid editing the output.

  1. Update the Control-Repo class definition for facts method to support the 'facts' key hash.
    Currently the control-repo class finds the facts hash at the root or nested the 'values' key of the factset json file. The output from the factset methods above will nest the facts under the 'facts' key at the parent level. To avoid editing the factset output each time it's generated, it would be ideal to update the self.facts() method definition to retrieve facts from 'values', 'facts' before defaulting to root level.

ref: onceover/lib/onceover/controlrepo.rb

#line 71 to 81
    def self.facts(filter = nil)
      # Would add a condition to look for the 'facts' key before defaulting to root. Atm only looks at 'values' key.
      @@existing_controlrepo.facts(filter, 'values'). 
    end

    def self.trusted_facts(filter = nil)
      @@existing_controlrepo.facts(filter, 'trusted')
    end

    def self.trusted_external_facts(filter = nil)
      @@existing_controlrepo.facts(filter, 'trusted_external')
    end

...
# Example: To obtain facts from 'facts' key hash in PuppetDB or Inventory API factset. 
# Reusing the 'values' key logic but searching for presence of 'facts' key in fact file before defaulting to root 
# 
#line 192 onwards
def facts(filter = nil, key = 'values')
      # Returns an array facts hashes
      all_facts = []
      logger.debug "Reading factsets"
      @facts_files.each do |file|
        facts_from_file = read_facts(file)
        # Facter 4 removed the top level key 'values' and, instead, puts facts
        # at the top level. The conditional below accounts for this.
        if (key.eql?('values') and facts_from_file.has_key?('values')) or !key.eql?('values')
          all_facts << facts_from_file[key]
        elsif (key.eql?('values') and facts_from_file.has_key?('facts')) # facts key present in puppetdb inventory factset
          all_facts << facts_from_file['facts']                                            # obtains from puppetdb factset 
        else
          all_facts << facts_from_file
        end
      end
      if filter
        # Allow us to pass a hash of facts to filter by
        raise "Filter param must be a hash" unless filter.is_a?(Hash)

        all_facts.keep_if do |hash|
          matches = []
          filter.each do |filter_fact,value|
            matches << keypair_is_in_hash(hash,filter_fact,value)
          end
          !matches.include? false
        end
      end
      return all_facts
    end

This should then support factsets like the ones below:

values hash
{
"certname": "<example-certname.foo.bar>",
"environment": "production",
"values": {
"agent_specified_environment": "production",
"aio_agent_build": "6.25.1",
"aio_agent_version": "6.25.1",
"architecture": "x86_64",
"augeas": {
"version": "1.12.0"
},
...
}

facts hash
{
"certname": "<example-certname.foo.bar>",
"environment": "production",
"facts": {
"agent_specified_environment": "production",
"aio_agent_build": "6.25.1",
"aio_agent_version": "6.25.1",
"architecture": "x86_64",
"augeas": {
"version": "1.12.0"
},
...
}
root facts
{
"certname": "<example-certname.foo.bar>",
"environment": "production",
"agent_specified_environment": "production",
"aio_agent_build": "6.25.1",
"aio_agent_version": "6.25.1",
"architecture": "x86_64",
"augeas": {
"version": "1.12.0"
...
}

@marcospjunior
Copy link

Try using the command puppet facts find --terminus puppetdb <certname>.
If you are using one of the latest agents, since the release of version 7, the default action for puppet facts is "puppet facts show" which displays the current node's facts. That's the reason for the empty factsets when passing the certname as a parameter.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants