Skip to content

Commit 2131af9

Browse files
committed
Merge pull request #1 from acidprime/master
Update from original
2 parents 78b7dd9 + f29ba17 commit 2131af9

File tree

5 files changed

+105
-26
lines changed

5 files changed

+105
-26
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,12 @@ to the `--threads` option. This will balence the catalogs evenly on the old and
9898
masters. This option defaults to 10 and in testing 50 threads seemed correct for
9999
4 masters with two load balancers.
100100

101+
Note: When using catalog diff to compare directories, one thread per catalog
102+
comparison will be created. However, since Ruby cannot take advantage of
103+
multiple CPUs this may be of limited use comparing local catalogs. If the
104+
'parallel' gem is installed, then one process will be forked off per CPU on the
105+
system, allowing use of all CPUs.
106+
101107
## Fact search
102108
You can pass `--fact_search` to filter the list of nodes based on a single fact value.
103109
This currently defaults to `kernel=Linux` if you do not pass it. The yaml cache will be

lib/puppet/catalog-diff/differ.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,12 @@ def diff(options = {})
4040
tmp = Marshal.load(File.read(r))
4141
when '.pson'
4242
tmp = PSON.load(File.read(r))
43+
unless tmp.respond_to? :version
44+
tmp = PSON.load({
45+
'document_type' => 'Catalog',
46+
'data' => PSON.load(File.read(r)),
47+
}.to_pson)
48+
end
4349
when '.json'
4450
tmp = PSON.load(File.read(r))
4551
else

lib/puppet/catalog-diff/formater.rb

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,57 @@ class Formater
55
def initialize()
66
end
77

8+
def format_simple(v, indent='', do_indent=false, comma='')
9+
str = ''
10+
str << indent if do_indent
11+
v = "\"#{v}\"" unless [Fixnum, TrueClass, FalseClass].include?(v.class)
12+
str << v.to_s << comma << "\n"
13+
end
14+
15+
def format_array(v, indent='', do_indent=false, comma='')
16+
str = ''
17+
str << indent if do_indent
18+
str << '[' << "\n"
19+
v.each do |val|
20+
str << format_value(val, "#{indent} ", true, ',')
21+
end
22+
str << "\t #{indent} ]" << "\n" << comma
23+
end
24+
25+
def format_hash(v, indent='', do_indent=false, comma='')
26+
str = ''
27+
str << indent if do_indent
28+
str << '{' << "\n"
29+
v.each do |key, val|
30+
str << "\t #{indent} #{key} => "
31+
str << format_value(val, "#{indent} ", true, ',', key)
32+
end
33+
str << "\t #{indent} }" << "\n" << comma
34+
end
35+
36+
def format_value(v, indent='', do_indent=false, comma='', k=nil)
37+
if v.is_a?(Array)
38+
format_array(v, indent, do_indent, comma)
39+
elsif v.is_a?(Hash)
40+
format_hash(v, indent, do_indent, comma)
41+
else
42+
v = v[:checksum] if (k == :content && v.is_a?(Hash))
43+
format_simple(v, indent, do_indent, comma)
44+
end
45+
end
46+
847
# creates a string representation of a resource that looks like Puppet code
948
def resource_to_string(resource)
1049
str = ''
1150
str << "\t" + resource[:type].downcase << '{"' << resource[:title].to_s << '":' << "\n"
1251
params = Hash[(resource[:parameters].sort_by {|k, v| k})]
1352
params.each_pair do |k,v|
14-
if v.is_a?(Array)
15-
indent = " " * k.to_s.size
16-
str << "\t #{k} => [" << "\n"
17-
v.each do |val|
18-
str << "\t #{indent} #{val}," << "\n"
19-
end
20-
str << "\t #{indent} ]" << "\n"
21-
else
22-
if k == :content
23-
v = v[:checksum]
24-
end
25-
str << "\t #{k} => #{v}" << "\n"
26-
end
53+
str << "\t #{k} => "
54+
indent = " " * k.to_s.size
55+
str << format_value(v, indent, false, '', k)
2756
end
2857
str << "\t}\n"
58+
str
2959
end
3060

3161
def node_summary_header(node,summary,key)

lib/puppet/catalog-diff/searchfacts.rb

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,24 @@ def find_nodes_puppetdb(env)
7373
connection = Puppet::Network::HttpPool.http_instance(Puppet::Util::Puppetdb.server,port,use_ssl)
7474
base_query = ["and", ["=", ["node","active"], true]]
7575
base_query.concat([["=", "catalog-environment", env]]) if env
76-
query = base_query.concat(@facts.map { |k, v| ["=", ["fact", k], v] })
76+
real_facts = @facts.select { |k, v| !v.nil? }
77+
query = base_query.concat(real_facts.map { |k, v| ["=", ["fact", k], v] })
78+
classes = Hash[@facts.select { |k, v| v.nil? }].keys
79+
classes.each do |c|
80+
capit = c.split('::').map{ |n| n.capitalize }.join('::')
81+
query = query.concat(
82+
[["in", "certname",
83+
["extract", "certname",
84+
["select-resources",
85+
["and",
86+
["=", "type", "Class"],
87+
["=", "title", capit ],
88+
],
89+
],
90+
],
91+
]]
92+
)
93+
end
7794
json_query = URI.escape(query.to_json)
7895
unless filtered = PSON.load(connection.request_get("/v4/nodes/?query=#{json_query}", {"Accept" => 'application/json'}).body)
7996
raise "Error parsing json output of puppet search"

lib/puppet/face/catalog/diff.rb

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
require 'puppet/face'
22
require 'thread'
33
require 'json'
4+
5+
begin
6+
require 'parallel'
7+
HAS_PARALLEL_GEM = true
8+
rescue LoadError
9+
HAS_PARALLEL_GEM = false
10+
end
11+
412
Puppet::Face.define(:catalog, '0.0.1') do
513

614
action :diff do
@@ -103,19 +111,29 @@
103111
found_catalogs = Puppet::CatalogDiff::FindCatalogs.new(catalog1,catalog2).return_catalogs(options)
104112
new_catalogs = found_catalogs.keys
105113

106-
thread_count = 1
107-
mutex = Mutex.new
108-
109-
thread_count.times.map {
110-
Thread.new(nodes,new_catalogs,options) do |nodes,new_catalogs,options|
111-
while new_catalog = mutex.synchronize { new_catalogs.pop }
112-
node_name = File.basename(new_catalog,File.extname(new_catalog))
113-
old_catalog = found_catalogs[new_catalog]
114-
node_summary = Puppet::CatalogDiff::Differ.new(old_catalog, new_catalog).diff(options)
115-
mutex.synchronize { nodes[node_name] = node_summary }
116-
end
114+
if HAS_PARALLEL_GEM
115+
results = Parallel.map(new_catalogs) do |new_catalog|
116+
node_name = File.basename(new_catalog,File.extname(new_catalog))
117+
old_catalog = found_catalogs[new_catalog]
118+
node_summary = Puppet::CatalogDiff::Differ.new(old_catalog, new_catalog).diff(options)
119+
[ node_name, node_summary ]
117120
end
118-
}.each(&:join)
121+
nodes = Hash[results]
122+
else
123+
thread_count = 1
124+
mutex = Mutex.new
125+
126+
thread_count.times.map {
127+
Thread.new(nodes,new_catalogs,options) do |nodes,new_catalogs,options|
128+
while new_catalog = mutex.synchronize { new_catalogs.pop }
129+
node_name = File.basename(new_catalog,File.extname(new_catalog))
130+
old_catalog = found_catalogs[new_catalog]
131+
node_summary = Puppet::CatalogDiff::Differ.new(old_catalog, new_catalog).diff(options)
132+
mutex.synchronize { nodes[node_name] = node_summary }
133+
end
134+
end
135+
}.each(&:join)
136+
end
119137
elsif File.file?(catalog1) && File.file?(catalog2)
120138
# User passed us two files
121139
node_name = File.basename(catalog2,File.extname(catalog2))
@@ -128,6 +146,8 @@
128146
pull_output = Puppet::Face[:catalog, '0.0.1'].pull(old_catalogs,new_catalogs,options[:fact_search],:old_server => catalog1,:new_server => catalog2,:changed_depth => options[:changed_depth], :threads => options[:threads], :use_puppetdb => options[:use_puppetdb])
129147
diff_output = Puppet::Face[:catalog, '0.0.1'].diff(old_catalogs,new_catalogs,options)
130148
nodes = diff_output
149+
FileUtils.rm_rf(old_catalogs)
150+
FileUtils.rm_rf(new_catalogs)
131151
nodes[:pull_output] = pull_output
132152
# Save the file as it can take a while to create
133153
if options[:output_report]

0 commit comments

Comments
 (0)