# How to write to a cloned node attribute

**URL:** <https://discourse.chef.io/t/how-to-write-to-a-cloned-node-attribute/10107>\
**Category:** Chef Infra (archive)\
**Created:** [December 22, 2016, 8:26pm UTC](https://discourse.chef.io/t/how-to-write-to-a-cloned-node-attribute/10107 "2016-12-22T20:26:55Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![ag4ve](https://avatars.discourse-cdn.com/v4/letter/a/a6a055/32.png) [@ag4ve](https://discourse.chef.io/u/ag4ve)\
**Post date:** [December 22, 2016, 8:26pm UTC](https://discourse.chef.io/t/how-to-write-to-a-cloned-node-attribute/10107/1 "2016-12-22T20:26:55Z")

</div>

I’ve written a provider and have a method to expand some data. However, even after I clone it, it still errors:

```
316 # Expand an array of hashes whose values may contain arrays into an array of hashes of strings
317 # This returns empty if an invalid data structure is given. the array within the hash must only contain strings.
318 # Expand [{'a' => 'aaa', 'b' => ['bbb', 'ccc'],...},...]
319 # Into [{'a' => 'aaa', 'b' => 'bbb'}, {'a' => 'aaa', 'b' => 'ccc'}]
320 def expand_rules(ruleset)
321 return unless ruleset.is_a?(Array)
322 rules = ruleset.clone
323 rules.each do |rule|
324 rule.each do |key,value|
325 if value.is_a?(Array)
326 value.each do |inel|
327 return unless inel.is_a?(String)
328 temp = rule.clone
329 temp[key] = inel
330 rules.push(temp)
331 end
332 break
333 end
334 end
335 end
336 # Remove temporary and oroginal data that should have been expanded
337 rules.reject{|rule| rule.any? {|key,value| value.is_a?(Array)}}
338 end

```

Which results in this stack trace:

```
Chef::Exceptions::ImmutableAttributeModification
------------------------------------------------
Node attributes are read-only when you do not specify which precedence level to set. To set an attribute use code like `node.default["key"] = "value"'

Cookbook Trace:
---------------
/var/chef/cache/cookbooks/icam_ipt/libraries/ipt_save.rb:328:in `initialize_clone'
/var/chef/cache/cookbooks/icam_ipt/libraries/ipt_save.rb:328:in `clone'
/var/chef/cache/cookbooks/icam_ipt/libraries/ipt_save.rb:328:in `block (3 levels) in expand_rules'
/var/chef/cache/cookbooks/icam_ipt/libraries/ipt_save.rb:326:in `each'
/var/chef/cache/cookbooks/icam_ipt/libraries/ipt_save.rb:326:in `block (2 levels) in expand_rules'
/var/chef/cache/cookbooks/icam_ipt/libraries/ipt_save.rb:324:in `each'
/var/chef/cache/cookbooks/icam_ipt/libraries/ipt_save.rb:324:in `block in expand_rules'
/var/chef/cache/cookbooks/icam_ipt/libraries/ipt_save.rb:323:in `each'
/var/chef/cache/cookbooks/icam_ipt/libraries/ipt_save.rb:323:in `expand_rules'
/var/chef/cache/cookbooks/icam_ipt/libraries/ipt_save.rb:245:in `insert_rules'
/var/chef/cache/cookbooks/icam_ipt/libraries/ipt_save.rb:219:in `block in action_compile'
/var/chef/cache/cookbooks/icam_ipt/libraries/ipt_save.rb:185:in `each'
/var/chef/cache/cookbooks/icam_ipt/libraries/ipt_save.rb:185:in `action_compile'
/var/chef/cache/cookbooks/icam_ipt/libraries/ipt_save.rb:113:in `action_all'

```

I found this, but I’m wondering if there’s a better way to accomplish this:

> <https://stackoverflow.com/questions/14738364/chef-11-any-way-to-turn-attributes-into-a-ruby-hash>

---

<div class="post-metadata">

**Author:** ![Tensibai](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/tensibai/32/29_2.png) [@Tensibai](https://discourse.chef.io/u/Tensibai)\
**Post date:** [December 23, 2016, 12:30pm UTC](https://discourse.chef.io/t/how-to-write-to-a-cloned-node-attribute/10107/2 "2016-12-23T12:30:51Z")

</div>

Main thing is `node['whatever']` is read-only (frozen) and should not be modified. `clone` does copy this state, so you can’t modify the input of your method.

To modify it you’ll have to call `node.default['whatever'] =`, `node.override['whatever'] =` or `node.set['whatever'] =`.  
You’re not giving any clue on how you call this method and why you’re doing things this way, so it’s hard to give an advice on how to tackle the real problem.

Edit after diggin in the code: using .dup instead of clone should work.

ref: [https://github.com/chef/chef/blob/master/lib/chef/node/immutable\_collections.rb](https://github.com/chef/chef/blob/master/lib/chef/node/immutable_collections.rb)
