Skip to content

Commit 88a9a31

Browse files
committed
Merge pull request #546 from jdevesa/validate_ip
Add validator for any IP address
2 parents 06b2cfb + fe23e01 commit 88a9a31

File tree

3 files changed

+129
-0
lines changed

3 files changed

+129
-0
lines changed

README.markdown

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1079,6 +1079,39 @@ Validates that the first argument is an integer (or an array of integers). Abort
10791079

10801080
*Type*: statement.
10811081

1082+
#### `validate_ip_address`
1083+
1084+
Validates that argument is an IP address, regardless of it is an IPv4 or an IPv6
1085+
address. It validates as well IP address with netmask. It must be an String, as
1086+
well.
1087+
1088+
The following values will pass:
1089+
1090+
~~~
1091+
validate_ip_address('0.0.0.0')
1092+
validate_ip_address('8.8.8.8')
1093+
validate_ip_address('127.0.0.1')
1094+
validate_ip_address('194.232.104.150')
1095+
validate_ip_address('3ffe:0505:0002::')
1096+
validate_ip_address('::1/64')
1097+
validate_ip_address('fe80::a00:27ff:fe94:44d6/64')
1098+
validate_ip_address('8.8.8.8/32')
1099+
~~~
1100+
1101+
The following values will fail, causing compilation to abort:
1102+
1103+
~~~
1104+
validate_ip_address(1)
1105+
validate_ip_address(true)
1106+
validate_ip_address(0.0.0.256)
1107+
validate_ip_address('::1', {})
1108+
validate_ip_address('0.0.0.0.0')
1109+
validate_ip_address('3.3.3')
1110+
validate_ip_address('23.43.9.22/64')
1111+
validate_ip_address('260.2.32.43')
1112+
~~~
1113+
1114+
10821115
#### `validate_numeric`
10831116

10841117
Validates that the first argument is a numeric value (or an array of numeric values). Aborts catalog compilation if any of the checks fail.
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
module Puppet::Parser::Functions
2+
3+
newfunction(:validate_ip_address, :doc => <<-ENDHEREDOC
4+
Validate that all values passed are valid IP addresses,
5+
regardless they are IPv4 or IPv6
6+
Fail compilation if any value fails this check.
7+
The following values will pass:
8+
$my_ip = "1.2.3.4"
9+
validate_ip_address($my_ip)
10+
validate_bool("8.8.8.8", "172.16.0.1", $my_ip)
11+
12+
$my_ip = "3ffe:505:2"
13+
validate_ip_address(1)
14+
validate_ip_address($my_ip)
15+
validate_bool("fe80::baf6:b1ff:fe19:7507", $my_ip)
16+
17+
The following values will fail, causing compilation to abort:
18+
$some_array = [ 1, true, false, "garbage string", "3ffe:505:2" ]
19+
validate_ip_address($some_array)
20+
ENDHEREDOC
21+
) do |args|
22+
23+
require "ipaddr"
24+
rescuable_exceptions = [ ArgumentError ]
25+
26+
if defined?(IPAddr::InvalidAddressError)
27+
rescuable_exceptions << IPAddr::InvalidAddressError
28+
end
29+
30+
unless args.length > 0 then
31+
raise Puppet::ParseError, ("validate_ip_address(): wrong number of arguments (#{args.length}; must be > 0)")
32+
end
33+
34+
args.each do |arg|
35+
unless arg.is_a?(String)
36+
raise Puppet::ParseError, "#{arg.inspect} is not a string."
37+
end
38+
39+
begin
40+
unless IPAddr.new(arg).ipv4? or IPAddr.new(arg).ipv6?
41+
raise Puppet::ParseError, "#{arg.inspect} is not a valid IP address."
42+
end
43+
rescue *rescuable_exceptions
44+
raise Puppet::ParseError, "#{arg.inspect} is not a valid IP address."
45+
end
46+
end
47+
48+
end
49+
50+
end
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
require 'spec_helper'
2+
3+
describe 'validate_ip_address' do
4+
describe 'signature validation' do
5+
it { is_expected.not_to eq(nil) }
6+
it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
7+
end
8+
9+
describe 'valid inputs' do
10+
it { is_expected.to run.with_params('0.0.0.0') }
11+
it { is_expected.to run.with_params('8.8.8.8') }
12+
it { is_expected.to run.with_params('127.0.0.1') }
13+
it { is_expected.to run.with_params('10.10.10.10') }
14+
it { is_expected.to run.with_params('194.232.104.150') }
15+
it { is_expected.to run.with_params('244.24.24.24') }
16+
it { is_expected.to run.with_params('255.255.255.255') }
17+
it { is_expected.to run.with_params('1.2.3.4', '5.6.7.8') }
18+
it { is_expected.to run.with_params('3ffe:0505:0002::') }
19+
it { is_expected.to run.with_params('3ffe:0505:0002::', '3ffe:0505:0002::2') }
20+
it { is_expected.to run.with_params('::1/64') }
21+
it { is_expected.to run.with_params('fe80::a00:27ff:fe94:44d6/64') }
22+
context 'with netmasks' do
23+
it { is_expected.to run.with_params('8.8.8.8/0') }
24+
it { is_expected.to run.with_params('8.8.8.8/16') }
25+
it { is_expected.to run.with_params('8.8.8.8/32') }
26+
it { is_expected.to run.with_params('8.8.8.8/255.255.0.0') }
27+
end
28+
end
29+
30+
describe 'invalid inputs' do
31+
it { is_expected.to run.with_params({}).and_raise_error(Puppet::ParseError, /is not a string/) }
32+
it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError, /is not a string/) }
33+
it { is_expected.to run.with_params(true).and_raise_error(Puppet::ParseError, /is not a string/) }
34+
it { is_expected.to run.with_params('one').and_raise_error(Puppet::ParseError, /is not a valid IP/) }
35+
it { is_expected.to run.with_params('0.0.0').and_raise_error(Puppet::ParseError, /is not a valid IP/) }
36+
it { is_expected.to run.with_params('0.0.0.256').and_raise_error(Puppet::ParseError, /is not a valid IP/) }
37+
it { is_expected.to run.with_params('0.0.0.0.0').and_raise_error(Puppet::ParseError, /is not a valid IP/) }
38+
it { is_expected.to run.with_params('1.2.3.4', {}).and_raise_error(Puppet::ParseError, /is not a string/) }
39+
it { is_expected.to run.with_params('1.2.3.4', 1).and_raise_error(Puppet::ParseError, /is not a string/) }
40+
it { is_expected.to run.with_params('1.2.3.4', true).and_raise_error(Puppet::ParseError, /is not a string/) }
41+
it { is_expected.to run.with_params('1.2.3.4', 'one').and_raise_error(Puppet::ParseError, /is not a valid IP/) }
42+
it { is_expected.to run.with_params('::1', {}).and_raise_error(Puppet::ParseError, /is not a string/) }
43+
it { is_expected.to run.with_params('::1', true).and_raise_error(Puppet::ParseError, /is not a string/) }
44+
it { is_expected.to run.with_params('::1', 'one').and_raise_error(Puppet::ParseError, /is not a valid IP/) }
45+
end
46+
end

0 commit comments

Comments
 (0)