Skip to content

Commit

Permalink
Rewrite validate_domain_name() as a Puppet 4.x function
Browse files Browse the repository at this point in the history
The 3.x function rely on is_domain_name() which is deprecated. Rewrite
it using the more modern puppet 4.x function to rely on data types for
better parameters validation.

While here, adjust the Stdlib::Fqdn data type to ensure the last
component (TLD) is non-numeric as [suggested by @ekohl](#1282 (comment)),
and add a Stdlib::Dns_zone data type that is basically the same but with
a trailing dot.
  • Loading branch information
smortex committed Apr 29, 2023
1 parent a241039 commit 4a0b112
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 65 deletions.
28 changes: 28 additions & 0 deletions lib/puppet/functions/validate_domain_name.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# frozen_string_literal: true

# @summary
# Validate that all values passed are syntactically correct domain names.
# Fail compilation if any value fails this check.
Puppet::Functions.create_function(:validate_domain_name) do
# @param values A domain name or an array of domain names to check
#
# @return [Undef]
# passes when the given values are syntactically correct domain names or raise an error when they are not and fails compilation
#
# @example Passing examples
# $my_domain_name = 'server.domain.tld'
# validate_domain_name($my_domain_name)
# validate_domain_name('domain.tld', 'puppet.com', $my_domain_name)
# validate_domain_name('www.example.2com')
#
# @example Failing examples (causing compilation to abort)
# validate_domain_name(1)
# validate_domain_name(true)
# validate_domain_name('invalid domain')
# validate_domain_name('-foo.example.com')
dispatch :validate_domain_name do
repeated_param 'Variant[Stdlib::Fqdn, Stdlib::Dns::Zone]', :values
end

def validate_domain_name(*_values); end
end
48 changes: 0 additions & 48 deletions lib/puppet/parser/functions/validate_domain_name.rb

This file was deleted.

27 changes: 13 additions & 14 deletions spec/functions/validate_domain_name_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
describe 'validate_domain_name' do
describe 'signature validation' do
it { is_expected.not_to eq(nil) }
it { is_expected.to run.with_params.and_raise_error(Puppet::ParseError, %r{wrong number of arguments}i) }
end

describe 'valid inputs' do
Expand All @@ -15,23 +14,23 @@
it { is_expected.to run.with_params('2foo.example.com', '2foo.example.com.') }
it { is_expected.to run.with_params('www.2foo.example.com', 'www.2foo.example.com.') }
it { is_expected.to run.with_params('domain.tld', 'puppet.com') }
it { is_expected.to run.with_params('www.example.2com') }
it { is_expected.to run.with_params('10.10.10.10.10') }
end

describe 'invalid inputs' do
it { is_expected.to run.with_params([]).and_raise_error(Puppet::ParseError, %r{is not a string}) }
it { is_expected.to run.with_params({}).and_raise_error(Puppet::ParseError, %r{is not a string}) }
it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError, %r{is not a string}) }
it { is_expected.to run.with_params(true).and_raise_error(Puppet::ParseError, %r{is not a string}) }
it { is_expected.to run.with_params([]).and_raise_error(ArgumentError, %r{got Array}) }
it { is_expected.to run.with_params({}).and_raise_error(ArgumentError, %r{got Hash}) }
it { is_expected.to run.with_params(1).and_raise_error(ArgumentError, %r{got Integer}) }
it { is_expected.to run.with_params(true).and_raise_error(ArgumentError, %r{got Boolean}) }

it { is_expected.to run.with_params('foo.example.com', []).and_raise_error(Puppet::ParseError, %r{is not a string}) }
it { is_expected.to run.with_params('foo.example.com', {}).and_raise_error(Puppet::ParseError, %r{is not a string}) }
it { is_expected.to run.with_params('foo.example.com', 1).and_raise_error(Puppet::ParseError, %r{is not a string}) }
it { is_expected.to run.with_params('foo.example.com', true).and_raise_error(Puppet::ParseError, %r{is not a string}) }
it { is_expected.to run.with_params('foo.example.com', []).and_raise_error(ArgumentError, %r{got Array}) }
it { is_expected.to run.with_params('foo.example.com', {}).and_raise_error(ArgumentError, %r{got Hash}) }
it { is_expected.to run.with_params('foo.example.com', 1).and_raise_error(ArgumentError, %r{got Integer}) }
it { is_expected.to run.with_params('foo.example.com', true).and_raise_error(ArgumentError, %r{got Boolean}) }

it { is_expected.to run.with_params('').and_raise_error(Puppet::ParseError, %r{is not a syntactically correct domain name}) }
it { is_expected.to run.with_params('invalid domain').and_raise_error(Puppet::ParseError, %r{is not a syntactically correct domain name}) }
it { is_expected.to run.with_params('-foo.example.com').and_raise_error(Puppet::ParseError, %r{is not a syntactically correct domain name}) }
it { is_expected.to run.with_params('www.example.2com').and_raise_error(Puppet::ParseError, %r{is not a syntactically correct domain name}) }
it { is_expected.to run.with_params('192.168.1.1').and_raise_error(Puppet::ParseError, %r{is not a syntactically correct domain name}) }
it { is_expected.to run.with_params('').and_raise_error(ArgumentError, %r{got ''}) }
it { is_expected.to run.with_params('invalid domain').and_raise_error(ArgumentError, %r{got 'invalid domain'}) }
it { is_expected.to run.with_params('-foo.example.com').and_raise_error(ArgumentError, %r{got '-foo\.example\.com'}) }
end
end
39 changes: 39 additions & 0 deletions spec/type_aliases/dns_zone_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# frozen_string_literal: true

require 'spec_helper'

describe 'Stdlib::Dns::Zone' do
describe 'accepts dns zones' do
[
'.',
'com.',
'example.com.',
'10.10.10.10.10.',
'xn--5ea.pf.',
].each do |value|
describe value.inspect do
it { is_expected.to allow_value(value) }
end
end
end

describe 'rejects other values' do
[
true,
false,
'',
'iAmAString',
{},
{ 'key' => 'value' },
{ 1 => 2 },
:undef,
3,
'www..com.',
'127.0.0.1',
].each do |value|
describe value.inspect do
it { is_expected.not_to allow_value(value) }
end
end
end
end
7 changes: 6 additions & 1 deletion spec/type_aliases/fqdn_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@

describe 'Stdlib::Fqdn' do
describe 'valid handling' do
['example', 'example.com', 'www.example.com'].each do |value|
[
'example',
'example.com',
'www.example.com',
'10.10.10.10.10',
].each do |value|
describe value.inspect do
it { is_expected.to allow_value(value) }
end
Expand Down
15 changes: 13 additions & 2 deletions spec/type_aliases/host_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,19 @@

describe 'Stdlib::Host' do
describe 'valid handling' do
['example', 'example.com', 'www.example.com', '2001:0db8:85a3:0000:0000:8a2e:0370:7334', 'fa76:8765:34ac:0823:ab76:eee9:0987:1111', '2001:0db8::1', '224.0.0.0', '255.255.255.255',
'0.0.0.0', '192.88.99.0'].each do |value|
[
'example',
'example.com',
'www.example.com',
'2001:0db8:85a3:0000:0000:8a2e:0370:7334',
'fa76:8765:34ac:0823:ab76:eee9:0987:1111',
'2001:0db8::1',
'224.0.0.0',
'255.255.255.255',
'0.0.0.0',
'192.88.99.0',
'10.10.10.10.10',
].each do |value|
describe value.inspect do
it { is_expected.to allow_value(value) }
end
Expand Down
2 changes: 2 additions & 0 deletions types/dns/zone.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# @summary Validate a DNS zone name
type Stdlib::Dns::Zone = Pattern[/\A((([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])\.)+|\.)\z/]

0 comments on commit 4a0b112

Please sign in to comment.