6a56d5c71b0552f673fbb78736e57b85073388eb
[mirror/dsa-puppet.git] / 3rdparty / modules / stdlib / lib / puppet / parser / functions / validate_integer.rb
1 #
2 # validate_interger.rb
3 #
4 module Puppet::Parser::Functions
5   newfunction(:validate_integer, :doc => <<-DOC
6     @summary
7       Validate that the first argument is an integer (or an array of integers). Abort catalog compilation if any of the checks fail.
8
9     The second argument is optional and passes a maximum. (All elements of) the first argument has to be less or equal to this max.
10     The third argument is optional and passes a minimum.  (All elements of) the first argument has to be greater or equal to this min.
11     If, and only if, a minimum is given, the second argument may be an empty string or undef, which will be handled to just check
12     if (all elements of) the first argument are greater or equal to the given minimum.
13     It will fail if the first argument is not an integer or array of integers, and if arg 2 and arg 3 are not convertable to an integer.
14
15     @return
16       Validate that the first argument is an integer (or an array of integers). Fail compilation if any of the checks fail.
17
18     @example **Usage**
19
20       The following values will pass:
21
22         validate_integer(1)
23         validate_integer(1, 2)
24         validate_integer(1, 1)
25         validate_integer(1, 2, 0)
26         validate_integer(2, 2, 2)
27         validate_integer(2, '', 0)
28         validate_integer(2, undef, 0)
29         $foo = undef
30         validate_integer(2, $foo, 0)
31         validate_integer([1,2,3,4,5], 6)
32         validate_integer([1,2,3,4,5], 6, 0)
33
34       Plus all of the above, but any combination of values passed as strings ('1' or "1").
35       Plus all of the above, but with (correct) combinations of negative integer values.
36
37       The following values will not:
38
39         validate_integer(true)
40         validate_integer(false)
41         validate_integer(7.0)
42         validate_integer({ 1 => 2 })
43         $foo = undef
44         validate_integer($foo)
45         validate_integer($foobaridontexist)
46
47         validate_integer(1, 0)
48         validate_integer(1, true)
49         validate_integer(1, '')
50         validate_integer(1, undef)
51         validate_integer(1, , 0)
52         validate_integer(1, 2, 3)
53         validate_integer(1, 3, 2)
54         validate_integer(1, 3, true)
55
56       Plus all of the above, but any combination of values passed as strings ('false' or "false").
57       Plus all of the above, but with incorrect combinations of negative integer values.
58       Plus all of the above, but with non-integer items in arrays or maximum / minimum argument.
59
60     DOC
61              ) do |args|
62     function_deprecation([:validate_integer, 'This method is deprecated, please use the stdlib validate_legacy function,
63                             with Stdlib::Compat::Integer. There is further documentation for validate_legacy function in the README.'])
64
65     # tell the user we need at least one, and optionally up to two other parameters
66     raise Puppet::ParseError, "validate_integer(): Wrong number of arguments; must be 1, 2 or 3, got #{args.length}" unless !args.empty? && args.length < 4
67
68     input, max, min = *args
69
70     # check maximum parameter
71     if args.length > 1
72       max = max.to_s
73       # allow max to be empty (or undefined) if we have a minimum set
74       if args.length > 2 && max == ''
75         max = nil
76       else
77         begin
78           max = Integer(max)
79         rescue TypeError, ArgumentError
80           raise Puppet::ParseError, "validate_integer(): Expected second argument to be unset or an Integer, got #{max}:#{max.class}"
81         end
82       end
83     else
84       max = nil
85     end
86
87     # check minimum parameter
88     if args.length > 2
89       begin
90         min = Integer(min.to_s)
91       rescue TypeError, ArgumentError
92         raise Puppet::ParseError, "validate_integer(): Expected third argument to be unset or an Integer, got #{min}:#{min.class}"
93       end
94     else
95       min = nil
96     end
97
98     # ensure that min < max
99     if min && max && min > max
100       raise Puppet::ParseError, "validate_integer(): Expected second argument to be larger than third argument, got #{max} < #{min}"
101     end
102
103     # create lamba validator function
104     validator = ->(num) do
105       # check input < max
106       if max && num > max
107         raise Puppet::ParseError, "validate_integer(): Expected #{input.inspect} to be smaller or equal to #{max}, got #{input.inspect}."
108       end
109       # check input > min (this will only be checked if no exception has been raised before)
110       if min && num < min
111         raise Puppet::ParseError, "validate_integer(): Expected #{input.inspect} to be greater or equal to #{min}, got #{input.inspect}."
112       end
113     end
114
115     # if this is an array, handle it.
116     case input
117     when Array
118       # check every element of the array
119       input.each_with_index do |arg, pos|
120         begin
121           raise TypeError if arg.is_a?(Hash)
122           arg = Integer(arg.to_s)
123           validator.call(arg)
124         rescue TypeError, ArgumentError
125           raise Puppet::ParseError, "validate_integer(): Expected element at array position #{pos} to be an Integer, got #{arg.class}"
126         end
127       end
128     # for the sake of compatibility with ruby 1.8, we need extra handling of hashes
129     when Hash
130       raise Puppet::ParseError, "validate_integer(): Expected first argument to be an Integer or Array, got #{input.class}"
131     # check the input. this will also fail any stuff other than pure, shiny integers
132     else
133       begin
134         input = Integer(input.to_s)
135         validator.call(input)
136       rescue TypeError, ArgumentError
137         raise Puppet::ParseError, "validate_integer(): Expected first argument to be an Integer or Array, got #{input.class}"
138       end
139     end
140   end
141 end