Skip to content

Commit 3378b3a

Browse files
authored
Merge pull request #1343 from puppetlabs/fqdn_rand_string
Rewrite fqdn_rand_string() as a Puppet 4.x function
2 parents c1fa4d2 + 42ad4f6 commit 3378b3a

File tree

3 files changed

+71
-93
lines changed

3 files changed

+71
-93
lines changed
+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# frozen_string_literal: true
2+
3+
# @summary
4+
# Generates a random alphanumeric string. Combining the `$fqdn` fact and an
5+
# optional seed for repeatable randomness.
6+
#
7+
# Optionally, you can specify a character set for the function (defaults to alphanumeric).
8+
Puppet::Functions.create_function(:fqdn_rand_string) do
9+
# @param length The length of the resulting string.
10+
# @param charset The character set to use.
11+
# @param The seed for repeatable randomness.
12+
#
13+
# @return [String]
14+
#
15+
# @example Example Usage:
16+
# fqdn_rand_string(10)
17+
# fqdn_rand_string(10, 'ABCDEF!@$%^')
18+
# fqdn_rand_string(10, '', 'custom seed')
19+
dispatch :fqdn_rand_string do
20+
param 'Integer[1]', :length
21+
optional_param 'String', :charset
22+
optional_repeated_param 'Any', :seed
23+
end
24+
25+
def fqdn_rand_string(length, charset = '', *seed)
26+
charset = charset.chars.to_a
27+
28+
charset = (0..9).map { |i| i.to_s } + ('A'..'Z').to_a + ('a'..'z').to_a if charset.empty?
29+
30+
rand_string = ''
31+
length.times do |current|
32+
rand_string += charset[call_function('fqdn_rand', charset.size, (seed + [current + 1]).join(':'))]
33+
end
34+
35+
rand_string
36+
end
37+
end

lib/puppet/parser/functions/fqdn_rand_string.rb

-41
This file was deleted.

spec/functions/fqdn_rand_string_spec.rb

+34-52
Original file line numberDiff line numberDiff line change
@@ -6,68 +6,50 @@
66
let(:default_charset) { %r{\A[a-zA-Z0-9]{100}\z} }
77

88
it { is_expected.not_to eq(nil) }
9-
it { is_expected.to run.with_params.and_raise_error(ArgumentError, %r{wrong number of arguments}i) }
10-
it { is_expected.to run.with_params(0).and_raise_error(ArgumentError, %r{first argument must be a positive integer}) }
11-
it { is_expected.to run.with_params(1.5).and_raise_error(ArgumentError, %r{first argument must be a positive integer}) }
12-
it { is_expected.to run.with_params(-10).and_raise_error(ArgumentError, %r{first argument must be a positive integer}) }
13-
it { is_expected.to run.with_params('-10').and_raise_error(ArgumentError, %r{first argument must be a positive integer}) }
14-
it { is_expected.to run.with_params('string').and_raise_error(ArgumentError, %r{first argument must be a positive integer}) }
15-
it { is_expected.to run.with_params([]).and_raise_error(ArgumentError, %r{first argument must be a positive integer}) }
16-
it { is_expected.to run.with_params({}).and_raise_error(ArgumentError, %r{first argument must be a positive integer}) }
17-
it { is_expected.to run.with_params(1, 1).and_raise_error(ArgumentError, %r{second argument must be undef or a string}) }
18-
it { is_expected.to run.with_params(1, []).and_raise_error(ArgumentError, %r{second argument must be undef or a string}) }
19-
it { is_expected.to run.with_params(1, {}).and_raise_error(ArgumentError, %r{second argument must be undef or a string}) }
9+
it { is_expected.to run.with_params.and_raise_error(ArgumentError, %r{expects at least 1 argument, got none}i) }
10+
it { is_expected.to run.with_params(0).and_raise_error(ArgumentError, %r{parameter 'length' expects an Integer\[1\] value, got Integer\[0, 0\]}) }
11+
it { is_expected.to run.with_params(1.5).and_raise_error(ArgumentError, %r{parameter 'length' expects an Integer\ value, got Float}) }
12+
it { is_expected.to run.with_params(-10).and_raise_error(ArgumentError, %r{parameter 'length' expects an Integer\[1\] value, got Integer\[-10, -10\]}) }
13+
it { is_expected.to run.with_params('-10').and_raise_error(ArgumentError, %r{parameter 'length' expects an Integer\ value, got String}) }
14+
it { is_expected.to run.with_params('string').and_raise_error(ArgumentError, %r{parameter 'length' expects an Integer\ value, got String}) }
15+
it { is_expected.to run.with_params([]).and_raise_error(ArgumentError, %r{parameter 'length' expects an Integer value, got Array}) }
16+
it { is_expected.to run.with_params({}).and_raise_error(ArgumentError, %r{parameter 'length' expects an Integer value, got Hash}) }
17+
it { is_expected.to run.with_params(1, 1).and_raise_error(ArgumentError, %r{parameter 'charset' expects a String value, got Integer}) }
18+
it { is_expected.to run.with_params(1, []).and_raise_error(ArgumentError, %r{parameter 'charset' expects a String value, got Array}) }
19+
it { is_expected.to run.with_params(1, {}).and_raise_error(ArgumentError, %r{parameter 'charset' expects a String value, got Hash}) }
20+
it { is_expected.to run.with_params('100').and_raise_error(ArgumentError, %r{parameter 'length' expects an Integer value, got String}) }
21+
it { is_expected.to run.with_params(100, nil).and_raise_error(ArgumentError, %r{parameter 'charset' expects a String value, got Undef}) }
2022
it { is_expected.to run.with_params(100).and_return(default_charset) }
21-
it { is_expected.to run.with_params('100').and_return(default_charset) }
22-
it { is_expected.to run.with_params(100, nil).and_return(default_charset) }
2323
it { is_expected.to run.with_params(100, '').and_return(default_charset) }
2424
it { is_expected.to run.with_params(100, 'a').and_return(%r{\Aa{100}\z}) }
2525
it { is_expected.to run.with_params(100, 'ab').and_return(%r{\A[ab]{100}\z}) }
2626
it { is_expected.to run.with_params(100, 'ãβ').and_return(%r{\A[ãβ]{100}\z}) }
2727

28-
it "provides the same 'random' value on subsequent calls for the same host" do
29-
expect(fqdn_rand_string(10)).to eql(fqdn_rand_string(10))
30-
end
31-
32-
it 'considers the same host and same extra arguments to have the same random sequence' do
33-
first_random = fqdn_rand_string(10, extra_identifier: [1, 'same', 'host'])
34-
second_random = fqdn_rand_string(10, extra_identifier: [1, 'same', 'host'])
35-
36-
expect(first_random).to eql(second_random)
37-
end
38-
39-
it 'allows extra arguments to control the random value on a single host' do
40-
first_random = fqdn_rand_string(10, extra_identifier: [1, 'different', 'host'])
41-
second_different_random = fqdn_rand_string(10, extra_identifier: [2, 'different', 'host'])
42-
43-
expect(first_random).not_to eql(second_different_random)
44-
end
45-
46-
it 'returns different strings for different hosts' do
47-
val1 = fqdn_rand_string(10, host: 'first.host.com')
48-
val2 = fqdn_rand_string(10, host: 'second.host.com')
49-
50-
expect(val1).not_to eql(val2)
51-
end
28+
context 'produce predictible and reproducible results' do
29+
before(:each) do
30+
if Gem::Version.new(Puppet::PUPPETVERSION) < Gem::Version.new('7.23.0')
31+
allow(scope).to receive(:lookupvar).with('::fqdn', {}).and_return(fqdn)
32+
else
33+
allow(scope).to receive(:lookupvar).with('facts', {}).and_return({ 'networking' => { 'fqdn' => fqdn } })
34+
end
35+
end
5236

53-
def fqdn_rand_string(max, args = {})
54-
host = args[:host] || '127.0.0.1'
55-
charset = args[:charset]
56-
extra = args[:extra_identifier] || []
37+
context 'on a node named example.com' do
38+
let(:fqdn) { 'example.com' }
5739

58-
# workaround not being able to use let(:facts) because some tests need
59-
# multiple different hostnames in one context
60-
if Gem::Version.new(Puppet::PUPPETVERSION) < Gem::Version.new('7.23.0')
61-
allow(scope).to receive(:lookupvar).with('::fqdn', {}).and_return(host)
62-
else
63-
allow(scope).to receive(:lookupvar).with('facts', {}).and_return({ 'networking' => { 'fqdn' => host } })
40+
it { is_expected.to run.with_params(5).and_return('Pw5NP') }
41+
it { is_expected.to run.with_params(10, 'abcd').and_return('cdadaaacaa') }
42+
it { is_expected.to run.with_params(20, '', 'custom seed').and_return('3QKQHP4wmEObY3a6hkeg') }
43+
it { is_expected.to run.with_params(20, '', 'custom seed', 1, 'extra').and_return('OA19SVDoc3QPY5NlSQ28') }
6444
end
6545

66-
function_args = [max]
67-
if args.key?(:charset) || !extra.empty?
68-
function_args << charset
46+
context 'on a node named desktop-fln40kq.lan' do
47+
let(:fqdn) { 'desktop-fln40kq.lan' }
48+
49+
it { is_expected.to run.with_params(5).and_return('bgQsB') }
50+
it { is_expected.to run.with_params(10, 'abcd').and_return('bcdbcdacad') }
51+
it { is_expected.to run.with_params(20, '', 'custom seed').and_return('KaZsFlWkUo5SeA3gBEf0') }
52+
it { is_expected.to run.with_params(20, '', 'custom seed', 1, 'extra').and_return('dcAzn1e8AA7hhoLpxAD6') }
6953
end
70-
function_args += extra
71-
scope.function_fqdn_rand_string(function_args)
7254
end
7355
end

0 commit comments

Comments
 (0)