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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
# This doesn't get stored in trac, since it changes every time.
providers = Puppet::Util::Reference.newreference :providers, :title => "Provider Suitability Report", :depth => 1, :dynamic => true, :doc => "Which providers are valid for this machine" do
types = []
Puppet::Type.loadall
Puppet::Type.eachtype do |klass|
next unless klass.providers.length > 0
types << klass
end
types.sort! { |a,b| a.name.to_s <=> b.name.to_s }
command_line = Puppet::Util::CommandLine.new
types.reject! { |type| ! command_line.args.include?(type.name.to_s) } unless command_line.args.empty?
ret = "Details about this host:\n\n"
# Throw some facts in there, so we know where the report is from.
["Ruby Version", "Puppet Version", "Operating System", "Operating System Release"].each do |label|
name = label.gsub(/\s+/, '')
value = Facter.value(name)
ret += option(label, value)
end
ret += "\n"
count = 1
# Produce output for each type.
types.each do |type|
features = type.features
ret += "\n" # add a trailing newline
# Now build up a table of provider suitability.
headers = %w{Provider Suitable?} + features.collect { |f| f.to_s }.sort
table_data = {}
functional = false
notes = []
begin
default = type.defaultprovider.name
rescue Puppet::DevError
default = "none"
end
type.providers.sort { |a,b| a.to_s <=> b.to_s }.each do |pname|
data = []
table_data[pname] = data
provider = type.provider(pname)
# Add the suitability note
if missing = provider.suitable?(false) and missing.empty?
data << "*X*"
suit = true
functional = true
else
data << "[#{count}]_" # A pointer to the appropriate footnote
suit = false
end
# Add a footnote with the details about why this provider is unsuitable, if that's the case
unless suit
details = ".. [#{count}]\n"
missing.each do |test, values|
case test
when :exists
details += " - Missing files #{values.join(", ")}\n"
when :variable
values.each do |name, facts|
if Puppet.settings.valid?(name)
details += " - Setting #{name} (currently #{Puppet.settings.value(name).inspect}) not in list #{facts.join(", ")}\n"
else
details += " - Fact #{name} (currently #{Facter.value(name).inspect}) not in list #{facts.join(", ")}\n"
end
end
when :true
details += " - Got #{values} true tests that should have been false\n"
when :false
details += " - Got #{values} false tests that should have been true\n"
when :feature
details += " - Missing features #{values.collect { |f| f.to_s }.join(",")}\n"
end
end
notes << details
count += 1
end
# Add a note for every feature
features.each do |feature|
if provider.features.include?(feature)
data << "*X*"
else
data << ""
end
end
end
ret += h(type.name.to_s + "_", 2)
ret += "[#{type.name}](#{"http://docs.puppetlabs.com/references/stable/type.html##{type.name}"})\n\n"
ret += option("Default provider", default)
ret += doctable(headers, table_data)
notes.each do |note|
ret += note + "\n"
end
ret += "\n"
end
ret += "\n"
ret
end
providers.header = "
Puppet resource types are usually backed by multiple implementations called `providers`,
which handle variance between platforms and tools.
Different providers are suitable or unsuitable on different platforms based on things
like the presence of a given tool.
Here are all of the provider-backed types and their different providers. Any unmentioned
types do not use providers yet.
"
|