Skip to content

Commit c990cc5

Browse files
committed
(PUP-10985) Output facts existing only in Facter 4 via diff action
This commit aims to improve the `puppet facts diff` CLI command by: - showing all differences between Facter 3 and Facter 4 (including facts available only in Facter 4) - sorting output results in alphabetical order for better human readability - allowing users to remove certain facts from output (via the `--exclude <regex>` CLI option) - including a CLI option to see results in a fully structured form - adding various code improvements
1 parent 42cb3a3 commit c990cc5

File tree

3 files changed

+424
-62
lines changed

3 files changed

+424
-62
lines changed

lib/puppet/face/facts.rb

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,19 @@
22
require 'puppet/node/facts'
33
require 'puppet/util/fact_dif'
44

5-
EXCLUDE_LIST = %w[ facterversion
6-
load_averages\..*
7-
processors\.speed
8-
swapfree swapfree_mb
9-
memoryfree memoryfree_mb
10-
memory\.swap\.available_bytes memory\.swap\.used_bytes
11-
memory\.swap\.available memory\.swap\.capacity memory\.swap\.used
12-
memory\.system\.available_bytes memory\.system\.used_bytes
13-
memory\.system\.available memory\.system\.capacity memory\.system\.used
14-
mountpoints\..*\.available.* mountpoints\..*\.capacity mountpoints\..*\.used.*
15-
sp_uptime system_profiler\.uptime
16-
uptime uptime_days uptime_hours uptime_seconds
17-
system_uptime\.uptime system_uptime\.days system_uptime\.hours system_uptime\.seconds
5+
EXCLUDE_LIST = %w[ ^facterversion$
6+
^load_averages\..*$
7+
^processors\.speed$
8+
^swapfree$ ^swapfree_mb$
9+
^memoryfree$ ^memoryfree_mb$
10+
^memory\.swap\.available_bytes$ ^memory\.swap\.used_bytes$
11+
^memory\.swap\.available$ ^memory\.swap\.capacity$ ^memory\.swap\.used$
12+
^memory\.system\.available_bytes$ ^memory\.system\.used_bytes$
13+
^memory\.system\.available$ ^memory\.system\.capacity$ ^memory\.system\.used$
14+
^mountpoints\..*\.available.*$ ^mountpoints\..*\.capacity$ ^mountpoints\..*\.used.*$
15+
^sp_uptime$ ^system_profiler\.uptime$
16+
^uptime$ ^uptime_days$ ^uptime_hours$ ^uptime_seconds$
17+
^system_uptime\.uptime$ ^system_uptime\.days$ ^system_uptime\.hours$ ^system_uptime\.seconds$
1818
]
1919

2020
Puppet::Indirector::Face.define(:facts, '0.0.1') do
@@ -117,7 +117,18 @@
117117
$ puppet facts diff
118118
EOT
119119

120+
option("--structured") do
121+
default_to { false }
122+
summary _("Render the different facts as structured.")
123+
end
124+
125+
option("--exclude " + _("<regex>")) do
126+
summary _("Regex used to exclude specific facts from diff.")
127+
end
128+
120129
when_invoked do |*args|
130+
options = args.pop
131+
121132
Puppet.settings.preferred_run_mode = :agent
122133
Puppet::Node::Facts.indirection.terminus_class = :facter
123134

@@ -133,7 +144,8 @@
133144
facter_3_result = Puppet::Util::Execution.execute("#{puppet_show_cmd} --no-facterng #{cmd_flags}")
134145
facter_ng_result = Puppet::Util::Execution.execute("#{puppet_show_cmd} --facterng #{cmd_flags}")
135146

136-
fact_diff = FactDif.new(facter_3_result, facter_ng_result, EXCLUDE_LIST)
147+
exclude_list = options[:exclude].nil? ? EXCLUDE_LIST : EXCLUDE_LIST + [ options[:exclude] ]
148+
fact_diff = FactDif.new(facter_3_result, facter_ng_result, exclude_list, options[:structured])
137149
fact_diff.difs
138150
else
139151
Puppet.warning _("Already using Facter 4. To use `puppet facts diff` remove facterng from the .conf file or run `puppet config set facterng false`.")
@@ -234,4 +246,3 @@
234246
end
235247
end
236248
end
237-

lib/puppet/util/fact_dif.rb

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,24 @@
11
require 'json'
22

33
class FactDif
4-
def initialize(old_output, new_output, exclude_list = [])
4+
def initialize(old_output, new_output, exclude_list, save_structured)
55
@c_facter = JSON.parse(old_output)
66
@next_facter = JSON.parse(new_output)
77
@exclude_list = exclude_list
8+
@save_structured = save_structured
9+
@flat_diff = []
810
@diff = {}
911
end
1012

1113
def difs
12-
search_hash(@c_facter, [])
14+
search_hash(((@c_facter.to_a - @next_facter.to_a) | (@next_facter.to_a - @c_facter.to_a)).to_h)
15+
16+
@flat_diff.sort_by { |a| a[0] }.each do |pair|
17+
fact_path = pair[0]
18+
value = pair[1]
19+
compare(fact_path, value, @c_facter)
20+
compare(fact_path, value, @next_facter)
21+
end
1322

1423
@diff
1524
end
@@ -28,35 +37,45 @@ def search_hash(sh, path = [])
2837
path.pop
2938
end
3039
else
31-
compare(path, sh)
40+
@flat_diff.push([path.dup, sh])
3241
end
3342
end
3443

35-
def compare(fact_path, old_value)
36-
new_value = @next_facter.dig(*fact_path)
37-
if different?(new_value, old_value) && !excluded?(fact_path.join('.'))
38-
@diff[fact_path.join('.')] = { new_value: new_value, old_value: old_value }
44+
def compare(fact_path, given_value, compared_hash)
45+
compared_value = compared_hash.dig(*fact_path)
46+
if different?(compared_value, given_value) && !excluded?(fact_path.join('.'))
47+
fact_path = fact_path.map{|f| f.to_s.include?('.') ? "\"#{f}\"" : f}.join('.') unless @save_structured
48+
if compared_hash == @c_facter
49+
bury(*fact_path, { :new_value => given_value, :old_value => compared_value }, @diff)
50+
else
51+
bury(*fact_path, { :new_value => compared_value, :old_value => given_value }, @diff)
52+
end
53+
end
54+
end
55+
56+
def bury(*paths, value, hash)
57+
if paths.count > 1
58+
path = paths.shift
59+
hash[path] = Hash.new unless hash.key?(path)
60+
bury(*paths, value, hash[path])
61+
else
62+
hash[*paths] = value
3963
end
4064
end
4165

4266
def different?(new, old)
43-
if old.is_a?(String) && new.is_a?(String)
67+
if old.is_a?(String) && new.is_a?(String) && (old.include?(',') || new.include?(','))
4468
old_values = old.split(',')
4569
new_values = new.split(',')
4670

47-
diff = old_values - new_values
48-
# also add new entries only available in Facter 4
49-
diff.concat(new_values - old_values)
50-
51-
return true if diff.any?
52-
53-
return false
71+
diff = (old_values - new_values) | (new_values - old_values)
72+
return diff.size.positive?
5473
end
5574

5675
old != new
5776
end
5877

5978
def excluded?(fact_name)
60-
@exclude_list.any? {|excluded_fact| fact_name =~ /^#{excluded_fact}$/}
79+
@exclude_list.any? {|excluded_fact| fact_name =~ /#{excluded_fact}/}
6180
end
6281
end

0 commit comments

Comments
 (0)