From b0fb47d4ec9490d1e4c4400c4bcf8b1c4456d327 Mon Sep 17 00:00:00 2001 From: WhatsARanjit Date: Sun, 12 Apr 2015 02:59:41 -0400 Subject: [PATCH] Added ability to specify section_prefix and section_suffix to accomodate files with sections that don't follow [section_name] format. AIX for example uses section_name: format. --- README.markdown | 28 ++ lib/puppet/provider/ini_setting/ruby.rb | 18 +- lib/puppet/type/ini_setting.rb | 11 + lib/puppet/util/ini_file.rb | 29 +- .../puppet/provider/ini_setting/ruby_spec.rb | 294 +++++++++++++++++- 5 files changed, 375 insertions(+), 5 deletions(-) diff --git a/README.markdown b/README.markdown index 017e8d715..80e8743c2 100644 --- a/README.markdown +++ b/README.markdown @@ -65,6 +65,24 @@ ini_subsetting {'sample subsetting': } ~~~ +###Use a non-standard section header + +~~~ +default: + minage = 1 + maxage = 13 + +ini_setting { 'default minage': + ensure => present, + path => '/etc/security/users', + section => 'default', + setting => 'minage', + value => '1', + section_prefix => '', + section_suffix => ':', +} +~~~ + ###Implement child providers @@ -176,6 +194,16 @@ Determines whether the specified setting should exist. Valid options: 'present' *Optional.* Supplies a value for the specified setting. Valid options: a string. Default value: undefined. +##### `section_prefix` + +*Optional.* Designates the string that will appear before the section's name. Default value: "[" + +##### `section_suffix` + +*Optional.* Designates the string that will appear after the section's name. Default value: "]" + +**NOTE:** The way this type finds all sections in the file is by looking for lines like `${section_prefix}${title}${section_suffix}` + ### Type: ini_subsetting diff --git a/lib/puppet/provider/ini_setting/ruby.rb b/lib/puppet/provider/ini_setting/ruby.rb index 7831a4fb0..245554199 100644 --- a/lib/puppet/provider/ini_setting/ruby.rb +++ b/lib/puppet/provider/ini_setting/ruby.rb @@ -94,9 +94,25 @@ def separator end end + def section_prefix + if resource.class.validattr?(:section_prefix) + resource[:section_prefix] || '[' + else + '[' + end + end + + def section_suffix + if resource.class.validattr?(:section_suffix) + resource[:section_suffix] || ']' + else + ']' + end + end + private def ini_file - @ini_file ||= Puppet::Util::IniFile.new(file_path, separator) + @ini_file ||= Puppet::Util::IniFile.new(file_path, separator, section_prefix, section_suffix) end end diff --git a/lib/puppet/type/ini_setting.rb b/lib/puppet/type/ini_setting.rb index b01f327ad..15ae2418c 100644 --- a/lib/puppet/type/ini_setting.rb +++ b/lib/puppet/type/ini_setting.rb @@ -39,5 +39,16 @@ desc 'The value of the setting to be defined.' end + newparam(:section_prefix) do + desc 'The prefix to the section name\'s header.' + + 'Defaults to \'[\'.' + defaultto('[') + end + + newparam(:section_suffix) do + desc 'The suffix to the section name\'s header.' + + 'Defaults to \']\'.' + defaultto(']') + end end diff --git a/lib/puppet/util/ini_file.rb b/lib/puppet/util/ini_file.rb index 0f1080bc2..e67e5b5d0 100644 --- a/lib/puppet/util/ini_file.rb +++ b/lib/puppet/util/ini_file.rb @@ -5,11 +5,14 @@ module Puppet module Util class IniFile - def initialize(path, key_val_separator = ' = ') + def initialize(path, key_val_separator = ' = ', section_prefix = '[', section_suffix = ']') k_v_s = key_val_separator.strip - @@SECTION_REGEX = /^\s*\[([^\]]*)\]\s*$/ + @section_prefix = section_prefix + @section_suffix = section_suffix + + @@SECTION_REGEX = section_regex @@SETTING_REGEX = /^(\s*)([^#;\s]|[^#;\s].*?[^\s#{k_v_s}])(\s*#{k_v_s}\s*)(.*)\s*$/ @@COMMENTED_SETTING_REGEX = /^(\s*)[#;]+(\s*)(.*?[^\s#{k_v_s}])(\s*#{k_v_s}[ \t]*)(.*)\s*$/ @@ -22,6 +25,26 @@ def initialize(path, key_val_separator = ' = ') end end + def section_regex + # Only put in prefix/suffix if they exist + # Also, if the prefix is '', the negated + # set match should be a match all instead. + r_string = '^\s*' + r_string += Regexp.escape(@section_prefix) + r_string += '(' + if @section_prefix != '' + r_string += '[^' + r_string += Regexp.escape(@section_prefix) + r_string += ']' + else + r_string += '.' + end + r_string += '*)' + r_string += Regexp.escape(@section_suffix) + r_string += '\s*$' + /#{r_string}/ + end + def section_names @section_names end @@ -107,7 +130,7 @@ def save whitespace_buffer = [] if (section.is_new_section?) && (! section.is_global?) - fh.puts("\n[#{section.name}]") + fh.puts("\n#{@section_prefix}#{section.name}#{@section_suffix}") end if ! section.is_new_section? diff --git a/spec/unit/puppet/provider/ini_setting/ruby_spec.rb b/spec/unit/puppet/provider/ini_setting/ruby_spec.rb index 0810bc284..c3f5ccfb6 100644 --- a/spec/unit/puppet/provider/ini_setting/ruby_spec.rb +++ b/spec/unit/puppet/provider/ini_setting/ruby_spec.rb @@ -137,6 +137,9 @@ def self.file_path subby=bar #another comment ; yet another comment + +-nonstandard- + shoes = purple EOS } @@ -164,6 +167,42 @@ def self.file_path subby=bar #another comment ; yet another comment + +-nonstandard- + shoes = purple + EOS +) + end + + it "should add a missing setting to the correct section with pre/suffix" do + resource = Puppet::Type::Ini_setting.new(common_params.merge( + :section => 'nonstandard', + :setting => 'yahoo', :value => 'yippee', + :section_prefix => '-', :section_suffix => '-')) + provider = described_class.new(resource) + provider.exists?.should be false + provider.create + validate_file(<<-EOS +# This is a comment +[section1] +; This is also a comment +foo=foovalue + +bar = barvalue +master = true +[section2] + +foo= foovalue2 +baz=bazvalue +url = http://192.168.1.1:8080 +[section:sub] +subby=bar + #another comment + ; yet another comment + +-nonstandard- + shoes = purple + yahoo = yippee EOS ) end @@ -191,6 +230,9 @@ def self.file_path subby=bar #another comment ; yet another comment + +-nonstandard- + shoes = purple yahoo = yippee EOS ) @@ -219,6 +261,41 @@ def self.file_path subby=bar #another comment ; yet another comment + +-nonstandard- + shoes = purple + EOS + ) + end + + it "should modify an existing setting with pre/suffix with a different value" do + resource = Puppet::Type::Ini_setting.new(common_params.merge( + :section => 'nonstandard', + :setting => 'shoes', :value => 'orange', + :section_prefix => '-', :section_suffix => '-' )) + provider = described_class.new(resource) + provider.exists?.should be true + provider.value=('orange') + validate_file(<<-EOS +# This is a comment +[section1] +; This is also a comment +foo=foovalue + +bar = barvalue +master = true +[section2] + +foo= foovalue2 +baz=bazvalue +url = http://192.168.1.1:8080 +[section:sub] +subby=bar + #another comment + ; yet another comment + +-nonstandard- + shoes = orange EOS ) end @@ -247,6 +324,9 @@ def self.file_path subby=foo #another comment ; yet another comment + +-nonstandard- + shoes = purple EOS ) end @@ -276,6 +356,43 @@ def self.file_path subby=bar #another comment ; yet another comment + +-nonstandard- + shoes = purple + EOS + ) + end + + it "should be able to handle settings with pre/suffix with non alphanumbering settings " do + resource = Puppet::Type::Ini_setting.new(common_params.merge( + :section => 'nonstandard', + :setting => 'shoes', :value => 'http://192.168.0.1:8080', + :section_prefix => '-', :section_suffix => '-' )) + provider = described_class.new(resource) + provider.exists?.should be true + provider.value.should == 'purple' + provider.value=('http://192.168.0.1:8080') + + validate_file( <<-EOS +# This is a comment +[section1] +; This is also a comment +foo=foovalue + +bar = barvalue +master = true +[section2] + +foo= foovalue2 +baz=bazvalue +url = http://192.168.1.1:8080 +[section:sub] +subby=bar + #another comment + ; yet another comment + +-nonstandard- + shoes = http://192.168.0.1:8080 EOS ) end @@ -287,6 +404,15 @@ def self.file_path provider.exists?.should be true end + it "should recognize an existing setting with pre/suffix with the specified value" do + resource = Puppet::Type::Ini_setting.new(common_params.merge( + :section => 'nonstandard', + :setting => 'shoes', :value => 'purple', + :section_prefix => '-', :section_suffix => '-' )) + provider = described_class.new(resource) + provider.exists?.should be true + end + it "should add a new section if the section does not exist" do resource = Puppet::Type::Ini_setting.new(common_params.merge( :section => "section3", :setting => 'huzzah', :value => 'shazaam')) @@ -311,12 +437,49 @@ def self.file_path #another comment ; yet another comment +-nonstandard- + shoes = purple + [section3] huzzah = shazaam EOS ) end + it "should add a new section with pre/suffix if the section does not exist" do + resource = Puppet::Type::Ini_setting.new(common_params.merge( + :section => "section3", :setting => 'huzzah', :value => 'shazaam', + :section_prefix => '-', :section_suffix => '-' )) + provider = described_class.new(resource) + provider.exists?.should be false + provider.create + validate_file(<<-EOS +# This is a comment +[section1] +; This is also a comment +foo=foovalue + +bar = barvalue +master = true +[section2] + +foo= foovalue2 +baz=bazvalue +url = http://192.168.1.1:8080 +[section:sub] +subby=bar + #another comment + ; yet another comment + +-nonstandard- + shoes = purple + +-section3- +huzzah = shazaam + EOS + ) + end + it "should add a new section if the section does not exist - with colon" do resource = Puppet::Type::Ini_setting.new(common_params.merge( :section => "section:subsection", :setting => 'huzzah', :value => 'shazaam')) @@ -341,12 +504,49 @@ def self.file_path #another comment ; yet another comment +-nonstandard- + shoes = purple + [section:subsection] huzzah = shazaam EOS ) end + it "should add a new section with pre/suffix if the section does not exist - with colon" do + resource = Puppet::Type::Ini_setting.new(common_params.merge( + :section => "section:subsection", :setting => 'huzzah', :value => 'shazaam', + :section_prefix => '-', :section_suffix => '-' )) + provider = described_class.new(resource) + provider.exists?.should be false + provider.create + validate_file(<<-EOS +# This is a comment +[section1] +; This is also a comment +foo=foovalue + +bar = barvalue +master = true +[section2] + +foo= foovalue2 +baz=bazvalue +url = http://192.168.1.1:8080 +[section:sub] +subby=bar + #another comment + ; yet another comment + +-nonstandard- + shoes = purple + +-section:subsection- +huzzah = shazaam + EOS + ) + end + it "should add a new section if no sections exists" do resource = Puppet::Type::Ini_setting.new(common_params.merge( :section => "section1", :setting => 'setting1', :value => 'hellowworld', :path => emptyfile)) @@ -359,6 +559,19 @@ def self.file_path ", emptyfile) end + it "should add a new section with pre/suffix if no sections exists" do + resource = Puppet::Type::Ini_setting.new(common_params.merge( + :section => "section1", :setting => 'setting1', :value => 'hellowworld', :path => emptyfile, + :section_prefix => '-', :section_suffix => '-' )) + provider = described_class.new(resource) + provider.exists?.should be false + provider.create + validate_file(" +-section1- +setting1 = hellowworld +", emptyfile) + end + it "should add a new section with colon if no sections exists" do resource = Puppet::Type::Ini_setting.new(common_params.merge( :section => "section:subsection", :setting => 'setting1', :value => 'hellowworld', :path => emptyfile)) @@ -371,6 +584,18 @@ def self.file_path ", emptyfile) end + it "should add a new section with pre/suffix with colon if no sections exists" do + resource = Puppet::Type::Ini_setting.new(common_params.merge( + :section => "section:subsection", :setting => 'setting1', :value => 'hellowworld', :path => emptyfile, + :section_prefix => '-', :section_suffix => '-' )) + provider = described_class.new(resource) + provider.exists?.should be false + provider.create + validate_file(" +-section:subsection- +setting1 = hellowworld +", emptyfile) + end it "should be able to handle variables of any type" do resource = Puppet::Type::Ini_setting.new(common_params.merge( :section => "section1", :setting => 'master', :value => true)) @@ -576,6 +801,9 @@ def self.file_path subby=bar #another comment ; yet another comment + + -nonstandard- + shoes = purple EOS } @@ -600,6 +828,38 @@ def self.file_path subby=bar #another comment ; yet another comment + + -nonstandard- + shoes = purple +EOS + ) + end + + it "should remove a setting with pre/suffix that exists" do + resource = Puppet::Type::Ini_setting.new(common_params.merge( + :section => 'nonstandard', :setting => 'shoes', :ensure => 'absent', + :section_prefix => '-', :section_suffix => '-' )) + provider = described_class.new(resource) + provider.exists?.should be true + provider.destroy + validate_file(<<-EOS +[section1] +; This is also a comment +foo=foovalue + +bar = barvalue +master = true +[section2] + +foo= foovalue2 +baz=bazvalue +url = http://192.168.1.1:8080 +[section:sub] +subby=bar + #another comment + ; yet another comment + + -nonstandard- EOS ) end @@ -626,11 +886,43 @@ def self.file_path subby=bar #another comment ; yet another comment + + -nonstandard- + shoes = purple EOS ) end - end + it "should do nothing for a setting with pre/suffix that does not exist" do + resource = Puppet::Type::Ini_setting.new(common_params.merge( + :section => 'nonstandard', :setting => 'foo', :ensure => 'absent', + :section_prefix => '-', :section_suffix => '-' )) + provider = described_class.new(resource) + provider.exists?.should be false + provider.destroy + validate_file(<<-EOS +[section1] +; This is also a comment +foo=foovalue + +bar = barvalue +master = true +[section2] + +foo= foovalue2 +baz=bazvalue +url = http://192.168.1.1:8080 +[section:sub] +subby=bar + #another comment + ; yet another comment + + -nonstandard- + shoes = purple + EOS + ) + end + end context "when dealing with indentation in sections" do let(:orig_content) {