In Chef 13.7 this attribute's default will end up attempting to modify the default value which is now frozen by default. Not using lazy will throw a runtime error in Chef 13.7
Here is the backtrace of the error:
================================================================================
Recipe Compile Error in /tmp/kitchen/cache/cookbooks/iptables-ng/resources/rule.rb
================================================================================
RuntimeError
------------
can't modify frozen Chef::Node::ImmutableArray
Cookbook Trace:
---------------
/tmp/kitchen/cache/cookbooks/iptables-ng/resources/rule.rb:32:in `class_from_file'
Relevant File Content:
----------------------
/tmp/kitchen/cache/cookbooks/iptables-ng/resources/rule.rb:
25: # As the name attribute will be used as a filename later
26: attribute :name, kind_of: String, name_attribute: true, regex: /^[-\w\.]+$/
27: # linux/netfilter/x_tables.h doesn't restrict chains very tightly. Just a string token
28: # with a max length of XT_EXTENSION_MAXLEN (29 in all 3.x headers I could find)
29: attribute :chain, kind_of: String, default: 'INPUT', regex: /^[\w-]{1,29}$/
30: attribute :table, kind_of: String, default: 'filter', equal_to: %w(filter nat mangle raw)
31: attribute :rule, kind_of: [Array, String], default: []
32>> attribute :ip_version, kind_of: [Array, Integer], default: node['iptables-ng']['enabled_ip_versions'], equal_to: [[4, 6], [4], [6], 4, 6]
33:
34: def path_for_chain
35: "/etc/iptables.d/#{table}/#{chain}"
36: end
37:
38: def path_for_ip_version(version)
39: "#{path_for_chain}/#{name}.rule_v#{version}"
40: end
41:
Additional information:
-----------------------
Ruby objects are often frozen to prevent further modifications
when they would negatively impact the process (e.g. values inside
Ruby's ENV class) or to prevent polluting other objects when default
values are passed by reference to many instances of an object (e.g.
the empty Array as a Chef resource default, passed by reference
to every instance of the resource).
Chef uses Object#freeze to ensure the default values of properties
inside Chef resources are not modified, so that when a new instance
of a Chef resource is created, and Object#dup copies values by
reference, the new resource is not receiving a default value that
has been by a previous instance of that resource.
Instead of modifying an object that contains a default value for all
instances of a Chef resource, create a new object and assign it to
the resource's parameter, e.g.:
fruit_basket = resource(:fruit_basket, 'default')
# BAD: modifies 'contents' object for all new fruit_basket instances
fruit_basket.contents << 'apple'
# GOOD: allocates new array only owned by this fruit_basket instance
fruit_basket.contents %w(apple)
System Info:
------------
chef_version=13.7.16
platform=ubuntu
platform_version=14.04
ruby=ruby 2.4.3p205 (2017-12-14 revision 61247) [x86_64-linux]
program_name=chef-client worker: ppid=1735;start=17:03:37;
executable=/opt/chef/bin/chef-client
In Chef 13.7 this attribute's default will end up attempting to modify the default value which is now frozen by default. Not using lazy will throw a runtime error in Chef 13.7
Here is the backtrace of the error: