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 28, 2023
1 parent 3cb8536 commit 0d72dcf
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 63 deletions.
28 changes: 28 additions & 0 deletions lib/puppet/functions/validate_domain_name.rb
@@ -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
# 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)
#
# @exapmle 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')
# validate_domain_name('www.example.2com')
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
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 @@ -18,20 +17,20 @@
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'}) }
it { is_expected.to run.with_params('www.example.2com').and_raise_error(ArgumentError, %r{got 'www\.example\.2com'}) }
it { is_expected.to run.with_params('192.168.1.1').and_raise_error(ArgumentError, %r{got '192\.168\.1\.1'}) }
end
end
39 changes: 39 additions & 0 deletions spec/type_aliases/dns_zone_spec.rb
@@ -0,0 +1,39 @@
# frozen_string_literal: true

require 'spec_helper'

describe 'Stdlib::Dns_zone' do
describe 'accepts dns zones' do
[
'.',
'com.',
'example.com.',
].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,
'2com.',
'com2.',
'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
2 changes: 2 additions & 0 deletions types/dns_zone.pp
@@ -0,0 +1,2 @@
# @summary Validate a DNS zone name
type Stdlib::Dns_zone = Pattern[/\A((([[:alnum:]]|[[:alnum:]][[:alnum:]-]*[[:alnum:]])\.)*[[:alpha:]]+\.|\.)\z/]
2 changes: 1 addition & 1 deletion types/fqdn.pp
@@ -1,2 +1,2 @@
# @summary Validate a Fully Qualified Domain Name
type Stdlib::Fqdn = Pattern[/\A(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])\z/]
type Stdlib::Fqdn = Pattern[/\A((([[:alnum:]]|[[:alnum:]][[:alnum:]-]*[[:alnum:]])\.)*[[:alpha:]]+)\z/]

0 comments on commit 0d72dcf

Please sign in to comment.