This repository has been archived by the owner on Dec 7, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 13
/
puppetdb.rb
106 lines (80 loc) · 3.15 KB
/
puppetdb.rb
1
2
3
4
5
6
7
8
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
require 'net/http'
require 'net/https'
module MCollective
class Discovery
class Puppetdb
def self.discover(filter, timeout, limit=0, client=nil)
http = Net::HTTP.new('puppetdb.devco.net', 443)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
found = []
filter.keys.each do |key|
case key
when "identity"
identity_search(filter["identity"], http, found)
when "cf_class"
class_search(filter["cf_class"], http, found)
when "fact"
fact_search(filter["fact"], http, found)
end
end
# filters are combined so we get the intersection of values across
# all matches found using fact, agent and identity filters
found = found.inject(found[0]){|x, y| x & y}
found.flatten.map do |node|
if node =~ /^(.+?)\.\w+\.net/
$1
else
node
end
end
end
def self.fact_search(filter, http, found)
return if filter.empty?
selected_hosts = []
filter.each do |fact|
raise "Can only do == matches using the PuppetDB discovery" unless fact[:operator] == "=="
query = ["and", ["=", ["fact", fact[:fact]], fact[:value]]]
resp, data = http.get("/nodes?query=%s" % URI.escape(query.to_json), {"accept" => "application/json"})
raise "Failed to retrieve nodes from PuppetDB: %s: %s" % [resp.code, resp.message] unless resp.code == "200"
found << JSON.parse(data)
end
end
def self.class_search(filter, http, found)
return if filter.empty?
selected_hosts = []
filter.each do |klass|
klass = klass.split("::").map{|i| i.capitalize}.join("::")
raise "Can not do regular expression matches for classes using the PuppetDB discovery method" if regexy_string(klass).is_a?(Regexp)
query = ["and", ["=", "type", "Class"], ["=", "title", klass]]
resp, data = http.get("/resources?query=%s" % URI.escape(query.to_json), {"accept" => "application/json"})
raise "Failed to retrieve nodes from PuppetDB: %s: %s" % [resp.code, resp.message] unless resp.code == "200"
found << JSON.parse(data).map{|found| found["certname"]}
end
end
def self.identity_search(filter, http, found)
return if filter.empty?
resp, data = http.get("/nodes", {"accept" => "application/json"})
raise "Failed to retrieve nodes from PuppetDB: %s: %s" % [resp.code, resp.message] unless resp.code == "200"
all_hosts = JSON.parse(data)
selected_hosts = []
filter.each do |identity|
identity = regexy_string(identity)
if identity.is_a?(Regexp)
selected_hosts << all_hosts.grep(identity)
else
selected_hosts << identity if all_hosts.include?(identity)
end
end
found << selected_hosts
end
def self.regexy_string(string)
if string.match("^/")
Regexp.new(string.gsub("\/", ""))
else
string
end
end
end
end
end