The Puppet Labs Issue Tracker has Moved: https://tickets.puppetlabs.com

This issue tracker is now in read-only archive mode and automatic ticket export has been disabled. Redmine users will need to create a new JIRA account to file tickets using https://tickets.puppetlabs.com. See the following page for information on filing tickets with JIRA:

Bug #16116

Arrays and hashes are mutable; new members can be added and existing values changed

Added by Nick Fagerlund over 3 years ago. Updated over 2 years ago.

Status:AcceptedStart date:08/24/2012
Priority:NormalDue date:
Assignee:-% Done:

0%

Category:language
Target version:3.x
Affected Puppet version: Branch:
Keywords:

We've Moved!

Ticket tracking is now hosted in JIRA: https://tickets.puppetlabs.com

This ticket is now tracked at: https://tickets.puppetlabs.com/browse/PUP-1245


Description

Courtesy Henrik: Puppet doesn’t let you reassign variables within a given scope, but it lets you change the values of hashes and arrays by mucking with their members. That seems wrong.

$myary = ['zero', 'one', 'two']
$myhash = {first => 'one', second => 'two', third => 'three'}

$myary[3] = 'three' #can insert new element 
$myary[3] = 'something else' #can reassign
notice($myary[3])

$myhash[fourth] = 'four' #can insert new element
$myhash[fourth] = 'something else' #can't reassign, fails compilation
notice($myhash[fourth])

$myary += ['four'] #can't append in same scope, fails compilation

AND it’s inconsistent, so obviously SOMETHING is whacked, even if we actually do want these objects to be mutable.

I don’t know what we should do about this. I think the extent to which this is being used in the wild is completely unknown.

History

#1 Updated by Anonymous over 3 years ago

  • Category set to language
  • Status changed from Unreviewed to Accepted
  • Target version set to 3.x

This is completely unwanted behavior.

[14:27:51][Ruby(ruby-1.9.3-p125)][Git(3.x)] andy:puppet
> puppet apply -e '$a = [1, 2] $a[0] = 3 notice($a)'
Scope(Class[main]): 3 2
Finished catalog run in 0.18 seconds

#2 Updated by Jan Vansteenkiste over 3 years ago

Probably related, when changing a hash in a erb template, the data structure also gets modified for any other template that uses the same hash.

You can find a (minimal) example here (gist). In this case, the workaround was to use .clone after getting the hash using scope.lookupvar.

#3 Updated by Henrik Lindberg about 3 years ago

Looked at the logic again. You are currently allowed to set the value of a hash key if it is not already set. For an array, it is always allowed to set a value.

So, this is both inconsistent and really bad.

#4 Updated by Frederic Schaer over 2 years ago

Hi,

I was hit by that one today, so I’d like to add it’s even still possible to delete hash keys using ERBs. Another (bad) thing : it seems the mutability warning disappeared from the “latest” doc, whereas it’s still present for 2.7. See:

http://docs.puppetlabs.com/puppet/2.7/reference/lang_datatypes.html#hashes

and

http://docs.puppetlabs.com/puppet/latest/reference/lang_datatypes.html#hashes

The following code will print a hash, delete a key in an inline template (this was my issue with 2 modules using the same source hash), and print the stripped hash :

class mytest::sub::class::one {
  $var='cheers'
  $hash={
    'test1'=>{key1 => $var},
    'test2'=>{key1 => "$var"},
    'test3'=>{key1 => 'thanks'},
  }
}

class mytest2 {
  include mytest::sub::class::one
  $hash=$mytest::sub::class::one::hash
  
  notify {'test2':
    message => inline_template('
11
11 <%= @hash.inspect %>
11
')
  }
  ->
  notify {'test':
    message => inline_template('
22
22 <% @newlist = @hash.delete_if{|k,v| v["key1"]!="cheers"} %>hash : <%= @hash.inspect %>
22 newlist : <%= @newlist.inspect %>
--

')
  }
  
}

include mytest2

This results in :

Notice:
11
11 {"test2"=>{"key1"=>"cheers"}, "test1"=>{"key1"=>"cheers"}, "test3"=>{"key1"=>"thanks"}}
11


Notice:
22
22 hash : {"test2"=>{"key1"=>"cheers"}, "test1"=>{"key1"=>"cheers"}}
22 newlist : {"test2"=>{"key1"=>"cheers"}, "test1"=>{"key1"=>"cheers"}}

#5 Updated by Nick Fagerlund over 2 years ago

Well, ERBs are a special case, and you can do all KINDS of horrible stuff in there, including reassigning scalar variables. :/

#6 Updated by Anonymous over 2 years ago

Redmine Issue #16116 has been migrated to JIRA:

https://tickets.puppetlabs.com/browse/PUP-1245

Also available in: Atom PDF