chr4-cookbooks / iptables-ng

Cookbook to maintain iptables rules and policies on different platforms, respecting the way the os handles these settings.
GNU General Public License v3.0
38 stars 32 forks source link

Use lazy eval for ip_version default because of a change in Chef 13.7 #70

Closed martinisoft closed 6 years ago

martinisoft commented 6 years ago

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
chr4 commented 6 years ago

Thanks for reporting and looking into this! LGTM.

chr4 commented 6 years ago

Released in 3.0.1