Issue #12543 has been updated by Chris Price.

Assignee deleted (Chris Price)


----------------------------------------
Bug #12543: Puppet::Type.hash2resource behavior depends on hash iteration order
https://projects.puppetlabs.com/issues/12543#change-65078

Author: Chris Price
Status: Accepted
Priority: Normal
Assignee: 
Category: 
Target version: 2.7.x
Affected Puppet version: 
Keywords: 
Branch: 
https://github.com/cprice-puppet/puppet/tree/bug/master/12543-hash2resource-depends-on-iteration-order


When writing a test that creates an inline instance of a type using a hash 
construct, e.g.:

<pre>
sleep_exec = Puppet::Type.type(:exec).new(
   :name => 'exec_spec sleep command',
   :command => "/usr/bin/ruby -e 'sleep 0.02'",
   :timeout => '0.01')
</pre>

the behavior may vary depending on the order that the particular ruby version 
happens to iterate over the hash values.

The problem occurs when the hash contains a value for both ":name" and whatever 
the namevar is for the type in question (in the example above, ":command").  In 
lib/puppet/type.rb, in hash2resource, there is a block that does this:

<pre>
    hash.each do |param, value|
      resource[param] = value
    end
</pre>

This calls into Puppet::Resource.[]=, which contains this line:

<pre>
    parameters[parameter_name(param)] = value
</pre>

The "parameter_name" method, in turn, will convert ":name" to the namevar value.

So... if the hash iteration in this example happens to iterate over ":command" 
before ":name", then the value for ":name" will overwrite the value for 
":command".  In this particular example that will completely break the code, 
because my ":name" value was never intended to be interpreted as a command.

This is probably a pathological case, because I think I was confusing the 
intent of ":title" with the intent of ":name"; however, there is still a bit of 
code smell here.

I'll add a link to a branch where this can be repro'd.  But, adding a print 
statement to the iteration loop in hash2resource, I see the following 
differences in output:

Linux, Ruby 1.8.7-p334
<pre>
 $ rspec -e "should fail if timeout is exceeded" ./spec/unit/type/exec_spec.rb
...
HASH2RESOURCE called
NEXT ITEM IN HASH: ':timeout'
NEXT ITEM IN HASH: ':name'
NEXT ITEM IN HASH: ':command'
...
</pre>

Win2k3, Ruby 1.8.7-p334
<pre>
    $ rspec -e "should fail if timeout is exceeded" 
./spec/unit/type/exec_spec.rb
...
HASH2RESOURCE called
NEXT ITEM IN HASH: ':timeout'
NEXT ITEM IN HASH: ':command'
NEXT ITEM IN HASH: ':name'
...
</pre>

On linux, "command" is the last value iterated over, so the resource gets the 
correct command and the test passes.

On windows, "name" is the last value iterated over, so it blows away the value 
of "command" and the test fails.




-- 
You have received this notification because you have either subscribed to it, 
or are involved in it.
To change your notification preferences, please click here: 
http://projects.puppetlabs.com/my/account

-- 
You received this message because you are subscribed to the Google Groups 
"Puppet Bugs" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/puppet-bugs?hl=en.

Reply via email to