puppet-ghostbuster icon indicating copy to clipboard operation
puppet-ghostbuster copied to clipboard

Use net/http instead of puppetdb-ruby

Open daenney opened this issue 9 years ago • 7 comments
trafficstars

The puppetdb-ruby gem provides a useful client but seems unable to encode more complex queries correctly causing APIError's to be thrown. Especially the classes query could benefit from a more efficient query on larger installations.

I'm having some trouble with Ruby right now but this should more or less be it:

require 'json'
require 'net/http'
require 'ghostbusters/version'


class PuppetGhostbuster
  class PuppetDB
    def self.client
      uri = URI.parse("#{ENV['PUPPETDB_URL'] || 'http://puppetdb:8080'}")

      @@client ||= Net::HTTP.new(uri.host, uri.port)
      @@client.key = ENV['PUPPETDB_KEY_FILE']
      @@client.cert = ENV['PUPPETDB_CERT_FILE']
      @@client.ca_file = ENV['PUPPETDB_CACERT_FILE']
    end

[..]

    def self.request(endpoint, query = nil)
      uri_prefix = '/pdb/query/v4'
      headers = {'user-agent' => "ghostbusters/#{PuppetGhostbuster::VERSION}", 'accept' => 'application/json' }
      if query.nil?
        request = Net::HTTP::Get.new("#{uri_prefix}/#{endpoint}", headers)
      else
        request = Net::HTTP::Get.new("#{uri_prefix}/#{endpoint}?query=#{URI.encode(query)}", headers)
      end
      resp = client.request(request)
      case resp
      when Net::HTTPSuccess
        JSON.parse resp.body
      else
        resp.value # calling value will raise an exception if we didn't get a 200
      end
    end
[..]

   def self.classes
      query = '["extract", [["function", "count"], "title"], ["=", "type", "Class"], ["group_by", "title"]]'
      @@classes ||= client.request('resources', query).select { |r| r.title }
  end

daenney avatar Jun 02 '16 11:06 daenney

@daenney wouldn't it be possible to fix puppetdb-ruby? @nathanielksmith what do you think?

mcanevet avatar Jun 02 '16 12:06 mcanevet

I took a look at that and it would be feasible but the project seems entirely abandoned. I'm not sure we'll ever see another release of it to be honest.

The easiest way for puppetdb-ruby would be to add an escape hatch, something along the lines of adding a raw_query parameter to the request method allowing you to escape the whole query builder thing so it doesn't have to be updated every time the PuppetDB query language changes. This would also allow it to support PQL with no further modifications. Albeit it's a bit less nice than when you can use query but it would stop blocking everyone.

daenney avatar Jun 02 '16 12:06 daenney

Sadly, I haven't been able to get work time to maintain puppetdb-ruby and no one has volunteered to take over the project.

It's wisest to probably just use raw http for now :( sorry for this tragedy of the commons situation.

vilmibm avatar Jun 02 '16 15:06 vilmibm

@daenney it will probably not be easy to do what this https://github.com/camptocamp/puppet-ghostbuster/blob/master/spec/spec_helper.rb#L6-L19 does for unit tests... I'm not sure it will be easily possible to convert complex puppetdb query to jgrep queries. But I like the idea of getting rid of an unmaintained piece of code.

mcanevet avatar Jun 07 '16 15:06 mcanevet

It sounds like the would be better solved with VCR: https://github.com/vcr/vcr

daenney avatar Jun 07 '16 16:06 daenney

@daenney did you already use VCR? I'm interested in using this instead of my hack with jgrep, but I can't find a simple doc about how to use it with rspec.

mcanevet avatar Jun 08 '16 13:06 mcanevet

The usage example in the README has always worked for me. Is there something there you'd like me to clarify?

daenney avatar Jun 09 '16 06:06 daenney