Class: Puppet::Resource::Puppetdb

Inherits:
Indirector::REST
  • Object
show all
Includes:
Util::Puppetdb
Defined in:
lib/puppet/indirector/resource/puppetdb.rb

Instance Method Summary collapse

Methods included from Util::Puppetdb

#config, config, included, log_x_deprecation_header, port, #profile, puppet3compat?, server, #submit_command, to_bool, to_wire_time, url_path

Instance Method Details

#build_expression(filter) ⇒ Object



66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/puppet/indirector/resource/puppetdb.rb', line 66

def build_expression(filter)
  return nil unless filter

  lhs, op, rhs = filter

  case op
  when '==', '!='
    build_predicate(op, lhs, rhs)
  when 'and', 'or'
    build_join(op, lhs, rhs)
  else
    raise Puppet::Error, "Operator #{op} in #{filter.inspect} not supported"
  end
end

#build_join(op, lhs, rhs) ⇒ Object



96
97
98
99
100
101
# File 'lib/puppet/indirector/resource/puppetdb.rb', line 96

def build_join(op, lhs, rhs)
  lhs = build_expression(lhs)
  rhs = build_expression(rhs)

  [op, lhs, rhs]
end

#build_predicate(op, field, value) ⇒ Object



81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/puppet/indirector/resource/puppetdb.rb', line 81

def build_predicate(op, field, value)
  # Title and tag aren't parameters, so we have to special-case them.
  expr = case field
         when "tag"
           # Tag queries are case-insensitive, so downcase them
           ["=", "tag", value.downcase]
         when "title"
           ["=", "title", value]
         else
           ["=", ['parameter', field], value]
         end

  op == '!=' ? ['not', expr] : expr
end

#headersObject



103
104
105
# File 'lib/puppet/indirector/resource/puppetdb.rb', line 103

def headers
  {'Accept' => 'application/json'}
end

#search(request) ⇒ Object



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/puppet/indirector/resource/puppetdb.rb', line 9

def search(request)
  profile("resource#search",
          [:puppetdb, :resource, :search, request.key]) do
    type   = request.key
    host   = request.options[:host]
    filter = request.options[:filter]
    scope  = request.options[:scope]

    # At minimum, we want to filter to the right type of exported resources.
    expr = ['and',
             ['=', 'type', type],
             ['=', 'exported', true],
             ['not',
               ['=', 'certname', host]]]

    filter_expr = build_expression(filter)
    expr << filter_expr if filter_expr

    query_param = CGI.escape(expr.to_json)

    begin
      url = Puppet::Util::Puppetdb.url_path("/v3/resources?query=#{query_param}")
      response = profile("Resources query: #{URI.unescape(url)}",
                         [:puppetdb, :resource, :search, :query, request.key]) do
        http_get(request, url, headers)
      end
      log_x_deprecation_header(response)

      unless response.is_a? Net::HTTPSuccess
        # Newline characters cause an HTTP error, so strip them
        raise "[#{response.code} #{response.message}] #{response.body.gsub(/[\r\n]/, '')}"
      end
    rescue => e
      raise Puppet::Error, "Could not retrieve resources from the PuppetDB at #{self.class.server}:#{self.class.port}: #{e}"
    end

    resources = profile("Parse resource query response (size: #{response.body.size})",
                        [:puppetdb, :resource, :search, :parse_query_response, request.key]) do
      JSON.load(response.body)
    end

    profile("Build up collected resource objects (count: #{resources.count})",
            [:puppetdb, :resource, :search, :build_up_collected_objects, request.key]) do
      resources.map do |res|
        params = res['parameters'] || {}
        params = params.map do |name,value|
          Puppet::Parser::Resource::Param.new(:name => name, :value => value)
        end
        attrs = {:parameters => params, :scope => scope}
        result = Puppet::Parser::Resource.new(res['type'], res['title'], attrs)
        result.collector_id = "#{res['certname']}|#{res['type']}|#{res['title']}"
        result
      end
    end
  end
end