hieracles 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/Gemfile +2 -0
- data/README.md +54 -8
- data/bin/hc +12 -6
- data/bin/ppdb +42 -0
- data/hc.1 +50 -8
- data/lib/hieracles.rb +2 -2
- data/lib/hieracles/config.rb +31 -19
- data/lib/hieracles/format.rb +4 -0
- data/lib/hieracles/formats/console.rb +49 -16
- data/lib/hieracles/formats/csv.rb +12 -8
- data/lib/hieracles/formats/json.rb +19 -6
- data/lib/hieracles/formats/plain.rb +24 -3
- data/lib/hieracles/formats/rawyaml.rb +4 -0
- data/lib/hieracles/formats/yaml.rb +4 -0
- data/lib/hieracles/node.rb +55 -10
- data/lib/hieracles/notification.rb +31 -0
- data/lib/hieracles/options/hc.rb +109 -0
- data/lib/hieracles/options/ppdb.rb +32 -0
- data/lib/hieracles/optparse.rb +4 -43
- data/lib/hieracles/puppetdb.rb +12 -0
- data/lib/hieracles/puppetdb/apierror.rb +10 -0
- data/lib/hieracles/puppetdb/client.rb +63 -0
- data/lib/hieracles/puppetdb/filter.rb +15 -0
- data/lib/hieracles/puppetdb/fixsslconnectionadapter.rb +25 -0
- data/lib/hieracles/puppetdb/query.rb +79 -0
- data/lib/hieracles/puppetdb/request.rb +44 -0
- data/lib/hieracles/puppetdb/response.rb +14 -0
- data/ppdb.1 +158 -0
- data/spec/files/config.yml +2 -0
- data/spec/files/config_withdb.yml +9 -0
- data/spec/files/facts.json +110 -0
- data/spec/files/facts.yaml +103 -0
- data/spec/files/hiera_columns.yaml +16 -0
- data/spec/files/hiera_deep.yaml +17 -0
- data/spec/files/hiera_deeper.yaml +17 -0
- data/spec/files/ssl/bad-ca.crt +1 -0
- data/spec/files/ssl/bad-cert.crt +1 -0
- data/spec/files/ssl/bad-key.pem +1 -0
- data/spec/files/ssl/ca.crt +16 -0
- data/spec/files/ssl/cert.crt +16 -0
- data/spec/files/ssl/key-pass.pem +18 -0
- data/spec/files/ssl/key.pem +15 -0
- data/spec/lib/config_spec.rb +51 -11
- data/spec/lib/format_spec.rb +5 -0
- data/spec/lib/formats/console_spec.rb +24 -3
- data/spec/lib/formats/csv_spec.rb +15 -0
- data/spec/lib/formats/json_spec.rb +22 -2
- data/spec/lib/formats/plain_spec.rb +23 -3
- data/spec/lib/formats/rawyaml_spec.rb +13 -0
- data/spec/lib/formats/yaml_spec.rb +138 -48
- data/spec/lib/hiera_spec.rb +0 -1
- data/spec/lib/hieracles_spec.rb +8 -0
- data/spec/lib/interpolate_spec.rb +49 -0
- data/spec/lib/node_spec.rb +50 -9
- data/spec/lib/notification_spec.rb +29 -0
- data/spec/lib/options/hc_spec.rb +82 -0
- data/spec/lib/optparse_spec.rb +7 -7
- data/spec/lib/puppetdb/apierror_spec.rb +11 -0
- data/spec/lib/puppetdb/client_spec.rb +64 -0
- data/spec/lib/puppetdb/fixsslconnectionadapter_spec.rb +107 -0
- data/spec/lib/puppetdb/query_spec.rb +39 -0
- data/spec/lib/puppetdb/request_spec.rb +61 -0
- data/spec/lib/puppetdb/response_spec.rb +13 -0
- data/spec/spec_helper.rb +4 -4
- metadata +133 -30
- data/Rakefile +0 -14
- data/hieracles.gemspec +0 -90
- data/lib/hieracles/help.rb +0 -38
- data/spec/lib/help_spec.rb +0 -8
| @@ -0,0 +1,32 @@ | |
| 1 | 
            +
            require 'hieracles/optparse'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Hieracles
         | 
| 4 | 
            +
              module Options
         | 
| 5 | 
            +
                class Ppdb < Hieracles::Optparse
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                  def available_options
         | 
| 8 | 
            +
                    {
         | 
| 9 | 
            +
                      version: {
         | 
| 10 | 
            +
                        has_arg: false,
         | 
| 11 | 
            +
                        aliases: ['v', 'version']
         | 
| 12 | 
            +
                      }
         | 
| 13 | 
            +
                    }
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  def self.usage
         | 
| 17 | 
            +
                    return <<-END
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            Usage: ppdb <endpoint> <command> [extra_args]
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            Available commands:
         | 
| 22 | 
            +
              node info <fqdn>
         | 
| 23 | 
            +
              node facts <fqdn>
         | 
| 24 | 
            +
              node resources <fqdn>
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                    END
         | 
| 27 | 
            +
                  end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
            end
         | 
| 32 | 
            +
                
         | 
    
        data/lib/hieracles/optparse.rb
    CHANGED
    
    | @@ -4,48 +4,9 @@ module Hieracles | |
| 4 4 |  | 
| 5 5 | 
             
                attr_reader :options, :payload
         | 
| 6 6 |  | 
| 7 | 
            -
                 | 
| 8 | 
            -
                   | 
| 9 | 
            -
             | 
| 10 | 
            -
                    aliases: ['c', 'conf', 'config']
         | 
| 11 | 
            -
                  },
         | 
| 12 | 
            -
                  format: {
         | 
| 13 | 
            -
                    has_arg: true,
         | 
| 14 | 
            -
                    aliases: ['f', 'format']
         | 
| 15 | 
            -
                  },
         | 
| 16 | 
            -
                  params: {
         | 
| 17 | 
            -
                    has_arg: true,
         | 
| 18 | 
            -
                    aliases: ['p', 'params']
         | 
| 19 | 
            -
                  },
         | 
| 20 | 
            -
                  hierafile: {
         | 
| 21 | 
            -
                    has_arg: true,
         | 
| 22 | 
            -
                    aliases: ['h', 'hierafile']
         | 
| 23 | 
            -
                  },
         | 
| 24 | 
            -
                  basepath: {
         | 
| 25 | 
            -
                    has_arg: true,
         | 
| 26 | 
            -
                    aliases: ['b', 'basepath']
         | 
| 27 | 
            -
                  },
         | 
| 28 | 
            -
                  encpath: {
         | 
| 29 | 
            -
                    has_arg: true,
         | 
| 30 | 
            -
                    aliases: ['e', 'encpath']
         | 
| 31 | 
            -
                  },
         | 
| 32 | 
            -
                  version: {
         | 
| 33 | 
            -
                    has_arg: false,
         | 
| 34 | 
            -
                    aliases: ['v', 'version']
         | 
| 35 | 
            -
                  },
         | 
| 36 | 
            -
                  yaml_facts: {
         | 
| 37 | 
            -
                    has_arg: true,
         | 
| 38 | 
            -
                    aliases: ['y', 'yaml']
         | 
| 39 | 
            -
                  },
         | 
| 40 | 
            -
                  json_facts: {
         | 
| 41 | 
            -
                    has_arg: true,
         | 
| 42 | 
            -
                    aliases: ['j', 'json']
         | 
| 43 | 
            -
                  },
         | 
| 44 | 
            -
                  interactive: {
         | 
| 45 | 
            -
                    has_arg: false,
         | 
| 46 | 
            -
                    aliases: ['i', 'interactive']
         | 
| 47 | 
            -
                  }
         | 
| 48 | 
            -
                }
         | 
| 7 | 
            +
                def available_options
         | 
| 8 | 
            +
                  {}
         | 
| 9 | 
            +
                end
         | 
| 49 10 |  | 
| 50 11 | 
             
                def initialize(array)
         | 
| 51 12 | 
             
                  @options = {}
         | 
| @@ -71,7 +32,7 @@ module Hieracles | |
| 71 32 |  | 
| 72 33 | 
             
                def optionkeys
         | 
| 73 34 | 
             
                  back = {}
         | 
| 74 | 
            -
                   | 
| 35 | 
            +
                  available_options.each do |k, v|
         | 
| 75 36 | 
             
                    v[:aliases].each do |a|
         | 
| 76 37 | 
             
                      back[a] = { var: k, has_args: v[:has_arg] }
         | 
| 77 38 | 
             
                    end
         | 
| @@ -0,0 +1,12 @@ | |
| 1 | 
            +
            require 'hieracles/puppetdb/fixsslconnectionadapter'
         | 
| 2 | 
            +
            require 'hieracles/puppetdb/apierror'
         | 
| 3 | 
            +
            require 'hieracles/puppetdb/query'
         | 
| 4 | 
            +
            require 'hieracles/puppetdb/filter'
         | 
| 5 | 
            +
            require 'hieracles/puppetdb/client'
         | 
| 6 | 
            +
            require 'hieracles/puppetdb/request'
         | 
| 7 | 
            +
            require 'hieracles/puppetdb/response'
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            module Hieracles
         | 
| 10 | 
            +
              module Puppetdb
         | 
| 11 | 
            +
              end
         | 
| 12 | 
            +
            end
         | 
| @@ -0,0 +1,63 @@ | |
| 1 | 
            +
            require 'httparty'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Hieracles
         | 
| 4 | 
            +
              module Puppetdb
         | 
| 5 | 
            +
                class Client
         | 
| 6 | 
            +
                  include HTTParty
         | 
| 7 | 
            +
             
         | 
| 8 | 
            +
                  def initialize(options, version = 3)
         | 
| 9 | 
            +
                    @version = version
         | 
| 10 | 
            +
                    setup_if_ssl(options)
         | 
| 11 | 
            +
                    options['port'] ||= 8080
         | 
| 12 | 
            +
                    options['host'] ||= 'localhost'
         | 
| 13 | 
            +
                    scheme = options['usessl'] ? "https://" : "http://"
         | 
| 14 | 
            +
                    self.class.base_uri(scheme + 
         | 
| 15 | 
            +
                      options['host'] +
         | 
| 16 | 
            +
                      ':' + options['port'].to_s +
         | 
| 17 | 
            +
                      '/v' + @version.to_s())
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  def setup_if_ssl(options)
         | 
| 21 | 
            +
                    if options['usessl']
         | 
| 22 | 
            +
                      self.class.default_options = {:options => options}
         | 
| 23 | 
            +
                      self.class.connection_adapter(FixSSLConnectionAdapter)
         | 
| 24 | 
            +
                    end
         | 
| 25 | 
            +
                  end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                  def request(endpoint, method = 'get', query = nil, opts = {})
         | 
| 28 | 
            +
                    ret = send("#{method}_request".to_sym, endpoint, query, opts)
         | 
| 29 | 
            +
                    if ret.code.to_s() =~ /^[4|5]/ or ret.parsed_response.length < 1
         | 
| 30 | 
            +
                      notifications = [ Hieracles::Notification.new('puppetdb', 'No match.', 'error') ]
         | 
| 31 | 
            +
                      Response.new({}, 0, notifications)
         | 
| 32 | 
            +
                    else
         | 
| 33 | 
            +
                      total = ret.headers['X-Records']
         | 
| 34 | 
            +
                      if total.nil?
         | 
| 35 | 
            +
                        total = ret.parsed_response.length
         | 
| 36 | 
            +
                      end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                      Response.new(ret.parsed_response, total)
         | 
| 39 | 
            +
                    end
         | 
| 40 | 
            +
                  end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                  def get_request(endpoint, query, opts)
         | 
| 43 | 
            +
                    path = "/" + endpoint
         | 
| 44 | 
            +
                    if query
         | 
| 45 | 
            +
                      json_query = JSON.dump(query)
         | 
| 46 | 
            +
                      filtered_opts = {'query' => json_query}
         | 
| 47 | 
            +
                      opts.each do |k,v|
         | 
| 48 | 
            +
                        if k == :counts_filter
         | 
| 49 | 
            +
                          filtered_opts['counts-filter'] = JSON.dump(v)
         | 
| 50 | 
            +
                        else
         | 
| 51 | 
            +
                          filtered_opts[k.to_s.sub("_", "-")] = v
         | 
| 52 | 
            +
                        end
         | 
| 53 | 
            +
                      end
         | 
| 54 | 
            +
                      puts path ; puts filtered_opts ; exit(0)
         | 
| 55 | 
            +
                      self.class.get(path, query: filtered_opts)
         | 
| 56 | 
            +
                    else
         | 
| 57 | 
            +
                      self.class.get(path)
         | 
| 58 | 
            +
                    end
         | 
| 59 | 
            +
                  end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                end
         | 
| 62 | 
            +
              end
         | 
| 63 | 
            +
            end
         | 
| @@ -0,0 +1,25 @@ | |
| 1 | 
            +
            require 'httparty'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Hieracles
         | 
| 4 | 
            +
              module Puppetdb
         | 
| 5 | 
            +
                class FixSSLConnectionAdapter < HTTParty::ConnectionAdapter
         | 
| 6 | 
            +
                  def attach_ssl_certificates(http, options)
         | 
| 7 | 
            +
                    raise(IOError, "Cert file #{options['cert']} not found.") unless File.exist? options['cert'].to_s
         | 
| 8 | 
            +
                    raise(IOError, "Key file #{options['key']} not found.") unless File.exist? options['key']
         | 
| 9 | 
            +
                    raise(IOError, "CA file #{options['ca_file']} not found.") unless File.exist? options['ca_file']
         | 
| 10 | 
            +
                    http.cert = OpenSSL::X509::Certificate.new(File.read(options['cert']))
         | 
| 11 | 
            +
                    if options['key_password']
         | 
| 12 | 
            +
                      http.key = OpenSSL::PKey::RSA.new(File.read(options['key']), options['key_password'])
         | 
| 13 | 
            +
                    else
         | 
| 14 | 
            +
                      http.key = OpenSSL::PKey::RSA.new(File.read(options['key']))
         | 
| 15 | 
            +
                    end
         | 
| 16 | 
            +
                    http.ca_file = options['ca_file']
         | 
| 17 | 
            +
                    if options['verify_peer']
         | 
| 18 | 
            +
                      http.verify_mode = OpenSSL::SSL::VERIFY_PEER
         | 
| 19 | 
            +
                    else
         | 
| 20 | 
            +
                      http.verify_mode = OpenSSL::SSL::VERIFY_NONE
         | 
| 21 | 
            +
                    end
         | 
| 22 | 
            +
                  end
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
            end
         | 
| @@ -0,0 +1,79 @@ | |
| 1 | 
            +
            module Hieracles
         | 
| 2 | 
            +
              module Puppetdb
         | 
| 3 | 
            +
                class Query
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                  def initialize(elements)
         | 
| 6 | 
            +
                    @elements = parse(elements)
         | 
| 7 | 
            +
                  end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                  def parse(elements)
         | 
| 10 | 
            +
                    items = []
         | 
| 11 | 
            +
                    index = 0
         | 
| 12 | 
            +
                    if elements.length > 1
         | 
| 13 | 
            +
                      elements.each do |e|
         | 
| 14 | 
            +
                        puts items.inspect
         | 
| 15 | 
            +
                        if e == 'or'
         | 
| 16 | 
            +
                          index++
         | 
| 17 | 
            +
                          continue
         | 
| 18 | 
            +
                        end
         | 
| 19 | 
            +
                        if /(.*)(>|<|=|!=|~)(.*)/.match e
         | 
| 20 | 
            +
                          items[index] ||= []
         | 
| 21 | 
            +
                          items[index] << [$2, $1, $3]
         | 
| 22 | 
            +
                        end
         | 
| 23 | 
            +
                      end
         | 
| 24 | 
            +
                    else
         | 
| 25 | 
            +
                      if /(.*)(>|<|=|!=|~)(.*)/.match elements[0]
         | 
| 26 | 
            +
                        items = [$2, $1, $3]
         | 
| 27 | 
            +
                      end
         | 
| 28 | 
            +
                    end
         | 
| 29 | 
            +
                    items
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  def output
         | 
| 33 | 
            +
                    back = []
         | 
| 34 | 
            +
                    if @elements.length > 1
         | 
| 35 | 
            +
                      back << 'or' 
         | 
| 36 | 
            +
                      @elements.each do |e|
         | 
| 37 | 
            +
                        back << build_and(e)
         | 
| 38 | 
            +
                      end
         | 
| 39 | 
            +
                    else
         | 
| 40 | 
            +
                      @elements.each do |e|
         | 
| 41 | 
            +
                        back << build_and(e)
         | 
| 42 | 
            +
                      end
         | 
| 43 | 
            +
                    end
         | 
| 44 | 
            +
                    back
         | 
| 45 | 
            +
                  end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                  def build_and(arrays)
         | 
| 48 | 
            +
                    if arrays.length > 1
         | 
| 49 | 
            +
                      ['and', arrays]
         | 
| 50 | 
            +
                    else
         | 
| 51 | 
            +
                      arrays
         | 
| 52 | 
            +
                    end
         | 
| 53 | 
            +
                  end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                  def defined?
         | 
| 56 | 
            +
                    @elements.count > 0
         | 
| 57 | 
            +
                  end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                  def match(item)
         | 
| 60 | 
            +
                    @elements.each do |e|
         | 
| 61 | 
            +
                      matched = false
         | 
| 62 | 
            +
                      e.each do |a|
         | 
| 63 | 
            +
                        case a[0]
         | 
| 64 | 
            +
                        when '='
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                        when '!='
         | 
| 67 | 
            +
                        when '<'
         | 
| 68 | 
            +
                        when '>'
         | 
| 69 | 
            +
                        when '!'
         | 
| 70 | 
            +
                        else
         | 
| 71 | 
            +
                        end
         | 
| 72 | 
            +
                      end
         | 
| 73 | 
            +
                      return true if matched
         | 
| 74 | 
            +
                    end
         | 
| 75 | 
            +
                  end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                end
         | 
| 78 | 
            +
              end
         | 
| 79 | 
            +
            end
         | 
| @@ -0,0 +1,44 @@ | |
| 1 | 
            +
            module Hieracles
         | 
| 2 | 
            +
              module Puppetdb
         | 
| 3 | 
            +
                class Request
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                  def initialize(options)
         | 
| 6 | 
            +
                    @client = Hieracles::Puppetdb::Client.new options
         | 
| 7 | 
            +
                  end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                  def node_info(fqdn)
         | 
| 10 | 
            +
                    @client.request("nodes/#{fqdn}")
         | 
| 11 | 
            +
                  end
         | 
| 12 | 
            +
                  alias_method :node_infos, :node_info
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                  def node_facts(fqdn, regex = //)
         | 
| 15 | 
            +
                    resp = @client.request("nodes/#{fqdn}/facts")
         | 
| 16 | 
            +
                    filter = Filter.new regex
         | 
| 17 | 
            +
                    resp.data = resp.data.reduce({}) do |a, d|
         | 
| 18 | 
            +
                      if filter.match(d['name'])
         | 
| 19 | 
            +
                        a[d['name'].to_sym] = d['value']
         | 
| 20 | 
            +
                      end
         | 
| 21 | 
            +
                      a
         | 
| 22 | 
            +
                    end
         | 
| 23 | 
            +
                    resp
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
                  alias_method :node_fact, :node_facts
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                  def node_resources(fqdn, *args)
         | 
| 28 | 
            +
                    resp = @client.request("nodes/#{fqdn}/resources")
         | 
| 29 | 
            +
                    field = args.shift
         | 
| 30 | 
            +
                    resp.data = resp.data.reduce({})  do |a, d|
         | 
| 31 | 
            +
                      if !field || Regexp.new(field).match(d['title'])
         | 
| 32 | 
            +
                        a[d['title']] = d
         | 
| 33 | 
            +
                      end
         | 
| 34 | 
            +
                      a
         | 
| 35 | 
            +
                    end
         | 
| 36 | 
            +
                    resp
         | 
| 37 | 
            +
                  end
         | 
| 38 | 
            +
                  alias_method :node_res, :node_resources
         | 
| 39 | 
            +
             | 
| 40 | 
            +
             | 
| 41 | 
            +
             | 
| 42 | 
            +
                end
         | 
| 43 | 
            +
              end
         | 
| 44 | 
            +
            end
         | 
| @@ -0,0 +1,14 @@ | |
| 1 | 
            +
            module Hieracles
         | 
| 2 | 
            +
              module Puppetdb
         | 
| 3 | 
            +
                class Response
         | 
| 4 | 
            +
                  attr_reader :data, :total_records, :notifications
         | 
| 5 | 
            +
                  attr_writer :data
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                  def initialize(data, total_records = nil, notifications = nil)
         | 
| 8 | 
            +
                    @data = data
         | 
| 9 | 
            +
                    @total_records = total_records
         | 
| 10 | 
            +
                    @notifications = notifications
         | 
| 11 | 
            +
                  end
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
            end
         | 
    
        data/ppdb.1
    ADDED
    
    | @@ -0,0 +1,158 @@ | |
| 1 | 
            +
            .TH ppdb 1 "2015-12-05" "version 0.2.1" "Hieracles command manual"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            .SH NAME
         | 
| 4 | 
            +
            ppdb \- Command line tool to query puppetdb
         | 
| 5 | 
            +
            .SH SYNOPSIS
         | 
| 6 | 
            +
            .B ppdb 
         | 
| 7 | 
            +
            .I object
         | 
| 8 | 
            +
            .I command
         | 
| 9 | 
            +
            .B [
         | 
| 10 | 
            +
            .I options
         | 
| 11 | 
            +
            .B ]
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            .SH DESCRIPTION
         | 
| 14 | 
            +
            .PP
         | 
| 15 | 
            +
            This tool is part of the Hieracles tools suite.
         | 
| 16 | 
            +
            .PP
         | 
| 17 | 
            +
            PuppetDB stores information gathered by Puppet when nodes run 
         | 
| 18 | 
            +
            the puppet client. It exposes a very neat REST interface, but 
         | 
| 19 | 
            +
            its query system can be a little complicated.
         | 
| 20 | 
            +
            .PP
         | 
| 21 | 
            +
            The purpose of 
         | 
| 22 | 
            +
            .B ppdb
         | 
| 23 | 
            +
            is to overlay the calls to the REST API and propose a more
         | 
| 24 | 
            +
            user-friendly way to query the Puppet Database (puppetdb).
         | 
| 25 | 
            +
            .PP
         | 
| 26 | 
            +
            Note that this tool is designed to work fine with the version 3 
         | 
| 27 | 
            +
            of the PuppetDB API.
         | 
| 28 | 
            +
            .PP
         | 
| 29 | 
            +
            Ref http://docs.puppetlabs.com/puppetdb/2.3/api/
         | 
| 30 | 
            +
            .PP
         | 
| 31 | 
            +
            .B ppdb
         | 
| 32 | 
            +
            takes at minimum 2 arguments, an object (or endpoint)
         | 
| 33 | 
            +
            and a subcommand, plus extra parameters depending the subcommand.
         | 
| 34 | 
            +
            .PP
         | 
| 35 | 
            +
            The object is like the endpoint in PuppetDB API, but we extend it 
         | 
| 36 | 
            +
            to a different list of possible objects:
         | 
| 37 | 
            +
             | 
| 38 | 
            +
            .IP node 10
         | 
| 39 | 
            +
            Uses the nodes endpoint. It accepts the subcommands:
         | 
| 40 | 
            +
            .RS
         | 
| 41 | 
            +
             | 
| 42 | 
            +
            .IP info 10
         | 
| 43 | 
            +
            will display the equivalent of 
         | 
| 44 | 
            +
            .I "GET /v3/nodes/<NODE>"
         | 
| 45 | 
            +
            and takes the node 
         | 
| 46 | 
            +
            .B certname
         | 
| 47 | 
            +
            as an argument. 
         | 
| 48 | 
            +
            .RS 10
         | 
| 49 | 
            +
            Optionaly, you can add a filter to limit what fields are displayed.
         | 
| 50 | 
            +
            .TP
         | 
| 51 | 
            +
            eg. ppdb node info <fqdn>
         | 
| 52 | 
            +
            .RS
         | 
| 53 | 
            +
            will display all the fields from the API response
         | 
| 54 | 
            +
            .RE
         | 
| 55 | 
            +
            eg. ppdb node info <fqdn> time
         | 
| 56 | 
            +
            .RS
         | 
| 57 | 
            +
            will only display the fields containing 
         | 
| 58 | 
            +
            .I time
         | 
| 59 | 
            +
            in their label.
         | 
| 60 | 
            +
            .RE
         | 
| 61 | 
            +
            .RE
         | 
| 62 | 
            +
             | 
| 63 | 
            +
            .IP facts 10
         | 
| 64 | 
            +
            will display the equivalent of 
         | 
| 65 | 
            +
            .I "GET /v3/nodes/<NODE>/facts"
         | 
| 66 | 
            +
            and takes the node 
         | 
| 67 | 
            +
            .B certname
         | 
| 68 | 
            +
            as an argument. 
         | 
| 69 | 
            +
            .RS 10
         | 
| 70 | 
            +
            As the result can be verbose, you can add a filter to limit what 
         | 
| 71 | 
            +
            fields are displayed.
         | 
| 72 | 
            +
            .TP
         | 
| 73 | 
            +
            eg. ppdb node facts <fqdn>
         | 
| 74 | 
            +
            .RS
         | 
| 75 | 
            +
            will display all the fields from the API response
         | 
| 76 | 
            +
            .RE
         | 
| 77 | 
            +
            eg. ppdb node facts <fqdn> memory
         | 
| 78 | 
            +
            .RS
         | 
| 79 | 
            +
            will only display the fields containing 
         | 
| 80 | 
            +
            .I memory
         | 
| 81 | 
            +
            in their label.
         | 
| 82 | 
            +
            .RE
         | 
| 83 | 
            +
            .RE
         | 
| 84 | 
            +
             | 
| 85 | 
            +
            .IP resources 10
         | 
| 86 | 
            +
            will display the equivalent of 
         | 
| 87 | 
            +
            .I "GET /v3/nodes/<NODE>/resources"
         | 
| 88 | 
            +
            and takes the node 
         | 
| 89 | 
            +
            .B certname
         | 
| 90 | 
            +
            as an argument. You can use 
         | 
| 91 | 
            +
            .I res
         | 
| 92 | 
            +
            instead of 
         | 
| 93 | 
            +
            .I resources
         | 
| 94 | 
            +
            for shorter.
         | 
| 95 | 
            +
            .RS 10
         | 
| 96 | 
            +
            As the result can be verbose, you can add a filter to limit what 
         | 
| 97 | 
            +
            resources are displayed.
         | 
| 98 | 
            +
            .TP
         | 
| 99 | 
            +
            eg. ppdb node res <fqdn>
         | 
| 100 | 
            +
            .RS
         | 
| 101 | 
            +
            will display all the fields from the API response
         | 
| 102 | 
            +
            .RE
         | 
| 103 | 
            +
            eg. ppdb node res <fqdn> nagios
         | 
| 104 | 
            +
            .RS
         | 
| 105 | 
            +
            will only display the fields containing 
         | 
| 106 | 
            +
            .I nagios
         | 
| 107 | 
            +
            in their label.
         | 
| 108 | 
            +
            .RE
         | 
| 109 | 
            +
            .RE
         | 
| 110 | 
            +
             | 
| 111 | 
            +
            .SH OPTIONS
         | 
| 112 | 
            +
             | 
| 113 | 
            +
            .TP
         | 
| 114 | 
            +
            .PD 0
         | 
| 115 | 
            +
            .B \-v
         | 
| 116 | 
            +
            .TP
         | 
| 117 | 
            +
            .PD
         | 
| 118 | 
            +
            .B \-\-version
         | 
| 119 | 
            +
            outputs version.
         | 
| 120 | 
            +
             | 
| 121 | 
            +
             | 
| 122 | 
            +
            .SH FILES
         | 
| 123 | 
            +
            .I ~/.config/hieracles/config.yaml
         | 
| 124 | 
            +
            .RS
         | 
| 125 | 
            +
            ppdb uses the same configuration file as hieracles, and relies on
         | 
| 126 | 
            +
            its information to find the url of the PuppetDB
         | 
| 127 | 
            +
             | 
| 128 | 
            +
            .SH EXAMPLES
         | 
| 129 | 
            +
            A typical config file would contain, at minimum:
         | 
| 130 | 
            +
            .PP
         | 
| 131 | 
            +
            .RS
         | 
| 132 | 
            +
            ---
         | 
| 133 | 
            +
            .RE
         | 
| 134 | 
            +
            .RS
         | 
| 135 | 
            +
            puppetdb:
         | 
| 136 | 
            +
            .RS
         | 
| 137 | 
            +
              usessl: false
         | 
| 138 | 
            +
            .RE
         | 
| 139 | 
            +
            .RS
         | 
| 140 | 
            +
              host: localhost
         | 
| 141 | 
            +
            .RE
         | 
| 142 | 
            +
            .RS
         | 
| 143 | 
            +
              port: 8080
         | 
| 144 | 
            +
            .RE
         | 
| 145 | 
            +
            .RE
         | 
| 146 | 
            +
             | 
| 147 | 
            +
            .SH SEE ALSO
         | 
| 148 | 
            +
            hiera(1), puppet(8), hc(1)
         | 
| 149 | 
            +
             | 
| 150 | 
            +
            .SH BUGS
         | 
| 151 | 
            +
            Please report any bug to https://github.com/Gandi/hieracles/issues
         | 
| 152 | 
            +
             | 
| 153 | 
            +
            .SH AUTHORS
         | 
| 154 | 
            +
            Copyright (c) 2015 gandi.net https://gandi.net
         | 
| 155 | 
            +
            .LP
         | 
| 156 | 
            +
            Hieracles is written by mose@gandi.net
         | 
| 157 | 
            +
            .LP
         | 
| 158 | 
            +
            https://github.com/Gandi/hieracles
         |