]> gitweb.fluxo.info Git - puppet-stdlib.git/commitdiff
(MODULES-1738) Don't modify global seed in fqdn_rotate()
authorEli Young <elyscape@gmail.com>
Wed, 28 Jan 2015 23:28:54 +0000 (15:28 -0800)
committerEli Young <elyscape@gmail.com>
Thu, 12 Feb 2015 22:04:47 +0000 (14:04 -0800)
As per puppetlabs/puppet@292233c, this leaves the global seed in a
deterministic state, which is bad. Puppet::Util.deterministic_rand()
exists to avoid running into this issue, but is only present starting in
Puppet 3.2.0.

lib/puppet/parser/functions/fqdn_rotate.rb
spec/functions/fqdn_rotate_spec.rb

index 7f4d37d01c0f73496d08836063d526030cd83a59..cf22d36813c0539e271457297323beff8cd1e7c7 100644 (file)
@@ -31,8 +31,20 @@ Rotates an array a random number of times based on a nodes fqdn.
 
     elements = result.size
 
-    srand(Digest::MD5.hexdigest([lookupvar('::fqdn'),arguments].join(':')).hex)
-    rand(elements).times {
+    seed = Digest::MD5.hexdigest([lookupvar('::fqdn'),arguments].join(':')).hex
+    # deterministic_rand() was added in Puppet 3.2.0; reimplement if necessary
+    if Puppet::Util.respond_to?(:deterministic_rand)
+      offset = Puppet::Util.deterministic_rand(seed, elements).to_i
+    else
+      if defined?(Random) == 'constant' && Random.class == Class
+        offset = Random.new(seed).rand(elements)
+      else
+        srand(seed)
+        offset = rand(elements)
+        srand()
+      end
+    end
+    offset.times {
        result.push result.shift
     }
 
index 40057d4f7473c9c57583f25f6b2412e08b34abc4..673a8a3214b60030df2add7f66c187fa787469fa 100755 (executable)
@@ -40,4 +40,21 @@ describe "the fqdn_rotate function" do
     result = scope.function_fqdn_rotate([value])
     result.size.should(eq(4))
   end
+
+  it "should use the Puppet::Util.deterministic_rand function if available" do
+    scope.expects(:lookupvar).with("::fqdn").returns("127.0.0.1")
+    if Puppet::Util.respond_to?(:deterministic_rand)
+      Puppet::Util.expects(:deterministic_rand).with(113646079810780526294648115052177588845,4)
+    end
+    scope.function_fqdn_rotate(["asdf"])
+  end
+
+  it "should not leave the global seed in a deterministic state" do
+    scope.expects(:lookupvar).with("::fqdn").returns("127.0.0.1").twice
+    scope.function_fqdn_rotate(["asdf"])
+    rand1 = rand()
+    scope.function_fqdn_rotate(["asdf"])
+    rand2 = rand()
+    expect(rand1).not_to eql(rand2)
+  end
 end