48736ad3f4fa9a35645a0696253f2d790e101795
[mirror/dsa-puppet.git] / 3rdparty / modules / stdlib / lib / puppet / functions / fact.rb
1 # Digs into the facts hash using dot-notation
2 #
3 # Example usage:
4 #
5 #     fact('osfamily')
6 #     fact('os.architecture')
7 #
8 # Array indexing:
9 #
10 #     fact('mountpoints."/dev".options.1')
11 #
12 # Fact containing a "." in the name:
13 #
14 #     fact('vmware."VRA.version"')
15 #
16 Puppet::Functions.create_function(:fact) do
17   dispatch :fact do
18     param 'String', :fact_name
19   end
20
21   def to_dot_syntax(array_path)
22     array_path.map { |string|
23       string.include?('.') ? %("#{string}") : string
24     }.join('.')
25   end
26
27   def fact(fact_name)
28     facts = closure_scope['facts']
29
30     # Transform the dot-notation string into an array of paths to walk. Make
31     # sure to correctly extract double-quoted values containing dots as single
32     # elements in the path.
33     path = fact_name.scan(%r{([^."]+)|(?:")([^"]+)(?:")}).map { |x| x.compact.first }
34
35     walked_path = []
36     path.reduce(facts) do |d, k|
37       return nil if d.nil? || k.nil?
38
39       if d.is_a?(Array)
40         begin
41           result = d[Integer(k)]
42         rescue ArgumentError => e # rubocop:disable Lint/UselessAssignment : Causes errors if assigment is removed.
43           Puppet.warning("fact request for #{fact_name} returning nil: '#{to_dot_syntax(walked_path)}' is an array; cannot index to '#{k}'")
44           result = nil
45         end
46       elsif d.is_a?(Hash)
47         result = d[k]
48       else
49         Puppet.warning("fact request for #{fact_name} returning nil: '#{to_dot_syntax(walked_path)}' is not a collection; cannot walk to '#{k}'")
50         result = nil
51       end
52
53       walked_path << k
54       result
55     end
56   end
57 end