add puppetlabs/inifile to 3rdparty
authorMartin Zobel-Helas <zobel@debian.org>
Sun, 21 Jun 2015 19:38:09 +0000 (19:38 +0000)
committerMartin Zobel-Helas <zobel@debian.org>
Sun, 21 Jun 2015 19:38:50 +0000 (19:38 +0000)
Signed-off-by: Martin Zobel-Helas <zobel@debian.org>
53 files changed:
3rdparty/Puppetfile
3rdparty/modules/inifile/CHANGELOG.md [new file with mode: 0644]
3rdparty/modules/inifile/CONTRIBUTING.md [new file with mode: 0644]
3rdparty/modules/inifile/Gemfile [new file with mode: 0644]
3rdparty/modules/inifile/LICENSE [new file with mode: 0644]
3rdparty/modules/inifile/README.markdown [new file with mode: 0644]
3rdparty/modules/inifile/Rakefile [new file with mode: 0644]
3rdparty/modules/inifile/checksums.json [new file with mode: 0644]
3rdparty/modules/inifile/lib/puppet/parser/functions/create_ini_settings.rb [new file with mode: 0644]
3rdparty/modules/inifile/lib/puppet/provider/ini_setting/ruby.rb [new file with mode: 0644]
3rdparty/modules/inifile/lib/puppet/provider/ini_subsetting/ruby.rb [new file with mode: 0644]
3rdparty/modules/inifile/lib/puppet/type/ini_setting.rb [new file with mode: 0644]
3rdparty/modules/inifile/lib/puppet/type/ini_subsetting.rb [new file with mode: 0644]
3rdparty/modules/inifile/lib/puppet/util/external_iterator.rb [new file with mode: 0644]
3rdparty/modules/inifile/lib/puppet/util/ini_file.rb [new file with mode: 0644]
3rdparty/modules/inifile/lib/puppet/util/ini_file/section.rb [new file with mode: 0644]
3rdparty/modules/inifile/lib/puppet/util/setting_value.rb [new file with mode: 0644]
3rdparty/modules/inifile/metadata.json [new file with mode: 0644]
3rdparty/modules/inifile/spec/acceptance/ini_setting_spec.rb [new file with mode: 0644]
3rdparty/modules/inifile/spec/acceptance/ini_subsetting_spec.rb [new file with mode: 0644]
3rdparty/modules/inifile/spec/acceptance/nodesets/centos-510-x64.yml [new file with mode: 0644]
3rdparty/modules/inifile/spec/acceptance/nodesets/centos-59-x64.yml [new file with mode: 0644]
3rdparty/modules/inifile/spec/acceptance/nodesets/centos-64-x64-pe.yml [new file with mode: 0644]
3rdparty/modules/inifile/spec/acceptance/nodesets/centos-64-x64.yml [new file with mode: 0644]
3rdparty/modules/inifile/spec/acceptance/nodesets/centos-65-x64.yml [new file with mode: 0644]
3rdparty/modules/inifile/spec/acceptance/nodesets/debian-607-x64.yml [new file with mode: 0644]
3rdparty/modules/inifile/spec/acceptance/nodesets/debian-73-x64.yml [new file with mode: 0644]
3rdparty/modules/inifile/spec/acceptance/nodesets/default.yml [new file with mode: 0644]
3rdparty/modules/inifile/spec/acceptance/nodesets/fedora-18-x64.yml [new file with mode: 0644]
3rdparty/modules/inifile/spec/acceptance/nodesets/sles-11sp1-x64.yml [new file with mode: 0644]
3rdparty/modules/inifile/spec/acceptance/nodesets/ubuntu-server-10044-x64.yml [new file with mode: 0644]
3rdparty/modules/inifile/spec/acceptance/nodesets/ubuntu-server-12042-x64.yml [new file with mode: 0644]
3rdparty/modules/inifile/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml [new file with mode: 0644]
3rdparty/modules/inifile/spec/acceptance/nodesets/windows-2003-i386.yml [new file with mode: 0644]
3rdparty/modules/inifile/spec/acceptance/nodesets/windows-2003r2-x86_64.yml [new file with mode: 0644]
3rdparty/modules/inifile/spec/acceptance/nodesets/windows-2008-x86_64.yml [new file with mode: 0644]
3rdparty/modules/inifile/spec/acceptance/nodesets/windows-2008r2-x86_64.yml [new file with mode: 0644]
3rdparty/modules/inifile/spec/acceptance/nodesets/windows-2012-x86_64.yml [new file with mode: 0644]
3rdparty/modules/inifile/spec/acceptance/nodesets/windows-2012r2-x86_64.yml [new file with mode: 0644]
3rdparty/modules/inifile/spec/classes/create_ini_settings_test_spec.rb [new file with mode: 0644]
3rdparty/modules/inifile/spec/classes/inherit_test1_spec.rb [new file with mode: 0644]
3rdparty/modules/inifile/spec/functions/create_ini_settings_spec.rb [new file with mode: 0644]
3rdparty/modules/inifile/spec/spec.opts [new file with mode: 0644]
3rdparty/modules/inifile/spec/spec_helper.rb [new file with mode: 0644]
3rdparty/modules/inifile/spec/spec_helper_acceptance.rb [new file with mode: 0644]
3rdparty/modules/inifile/spec/unit/puppet/provider/ini_setting/inheritance_spec.rb [new file with mode: 0644]
3rdparty/modules/inifile/spec/unit/puppet/provider/ini_setting/ruby_spec.rb [new file with mode: 0644]
3rdparty/modules/inifile/spec/unit/puppet/provider/ini_subsetting/ruby_spec.rb [new file with mode: 0644]
3rdparty/modules/inifile/spec/unit/puppet/util/external_iterator_spec.rb [new file with mode: 0644]
3rdparty/modules/inifile/spec/unit/puppet/util/ini_file_spec.rb [new file with mode: 0644]
3rdparty/modules/inifile/spec/unit/puppet/util/setting_value_spec.rb [new file with mode: 0644]
3rdparty/modules/inifile/tests/ini_setting.pp [new file with mode: 0644]
3rdparty/modules/inifile/tests/ini_subsetting.pp [new file with mode: 0644]

index 86237bb..d3c0c2d 100644 (file)
@@ -6,5 +6,7 @@ forge "http://forge.puppetlabs.com"
 mod 'puppetlabs/stdlib', '4.6.0'
 mod 'puppetlabs/concat', '1.2.2'
 mod 'puppetlabs/rabbitmq', '5.2.1'
+mod 'puppetlabs/inifile', '1.3.0'
+
 mod 'elasticsearch/elasticsearch', '0.9.5'
 mod 'nanliu/staging', '1.0.3'
diff --git a/3rdparty/modules/inifile/CHANGELOG.md b/3rdparty/modules/inifile/CHANGELOG.md
new file mode 100644 (file)
index 0000000..375e910
--- /dev/null
@@ -0,0 +1,211 @@
+##2015-06-09 - Supported Releases 1.3.0
+###Summary
+
+This is primarily a feature release, but also includes test fixes, documentation updates and synchronization of files with modulesync.
+
+####Features
+- Synchronized files using modulesync
+- Improved documentation
+- Allow changing key value separator beyond indentation
+- Adding the ability to change regex match for $section in inifile
+
+####Bugfixes
+- pin beaker-rspec for windows testing
+- pin rspec gems for testing
+- Adds default values for section
+- Fixed names containing spaces
+
+##2014-11-11 - Supported Releases 1.2.0
+###Summary
+
+This is primarily a bugfix release, but also includes documentation updates and synchronization of files with modulesync.
+
+####Features
+- Synchronized files using modulesync
+- Improved documentation with a warning about old, manually installed inifile with PE3.3+
+
+####Bugfixes
+- Fix issue where single character settings were not being saved
+
+##2014-09-30 - Supported Releases 1.1.4
+###Summary
+
+This release includes documentation and test updates.
+
+##2014-07-15 - Supported Release 1.1.3
+###Summary
+
+This release merely updates metadata.json so the module can be uninstalled and
+upgraded via the puppet module command.
+
+##2014-07-10 - Supported Release 1.1.2
+###Summary
+
+This is a re-packaging release.
+
+##2014-07-07 - Release 1.1.1
+###Summary
+
+This supported bugfix release corrects the inifile section header detection
+regex (so you can use more characters in your section titles).
+
+####Bugfixes
+- Correct section regex to allow anything other than ]
+- Correct `exists?` to return a boolean
+- Lots of test updates
+- Add missing CONTRIBUTING.md
+
+##2014-06-04 - Release 1.1.0
+###Summary
+
+This is a compatibility and feature release.  This release adds one new
+feature, the ability to control the quote character used.  This allows you to
+do things like:
+
+```
+ini_subsetting { '-Xms':
+    ensure     => present,
+    path       => '/some/config/file',
+    section    => '',
+    setting    => 'JAVA_ARGS',
+    quote_char => '"',
+    subsetting => '-Xms'
+    value      => '256m',
+  }
+```
+
+Which builds:
+
+```
+JAVA_ARGS="-Xmx256m -Xms256m"
+```
+
+####Features
+- Add quote_char parameter to the ini_subsetting resource type
+
+####Bugfixes
+
+####Known Bugs
+* No known bugs
+
+##2014-03-04 - Supported Release 1.0.3
+###Summary
+
+This is a supported release.  It has only test changes.
+
+####Features
+
+####Bugfixes
+
+####Known Bugs
+* No known bugs
+
+
+##2014-02-26 - Version 1.0.2
+###Summary
+This release adds supported platforms to metadata.json and contains spec fixes
+
+
+##2014-02-12 - Version 1.0.1
+###Summary
+This release is a bugfix for handling whitespace/[]'s better, and adding a
+bunch of tests.
+
+####Bugfixes
+- Handle whitespace in sections
+- Handle square brances in values
+- Add metadata.json
+- Update some travis testing
+- Tons of beaker-rspec tests
+
+
+##2013-07-16 - Version 1.0.0
+####Features
+- Handle empty values.
+- Handle whitespace in settings names (aka: server role = something)
+- Add mechanism for allowing ini_setting subclasses to override the
+formation of the namevar during .instances, to allow for ini_setting
+derived types that manage flat ini-file-like files and still purge
+them.
+
+---
+##2013-05-28 - Chris Price <chris@puppetlabs.com> - 0.10.3
+ * Fix bug in subsetting handling for new settings (cbea5dc)
+
+##2013-05-22 - Chris Price <chris@puppetlabs.com> - 0.10.2
+ * Better handling of quotes for subsettings (1aa7e60)
+
+##2013-05-21 - Chris Price <chris@puppetlabs.com> - 0.10.1
+ * Change constants to class variables to avoid ruby warnings (6b19864)
+
+##2013-04-10 - Erik DalĂ©n <dalen@spotify.com> - 0.10.1
+ * Style fixes (c4af8c3)
+
+##2013-04-02 - Dan Bode <dan@puppetlabs.com> - 0.10.1
+ * Add travisfile and Gemfile (c2052b3)
+
+##2013-04-02 - Chris Price <chris@puppetlabs.com> - 0.10.1
+ * Update README.markdown (ad38a08)
+
+##2013-02-15 - Karel Brezina <karel.brezina@gmail.com> - 0.10.0
+ * Added 'ini_subsetting' custom resource type (4351d8b)
+
+##2013-03-11 - Dan Bode <dan@puppetlabs.com> - 0.10.0
+ * guard against nil indentation values (5f71d7f)
+
+##2013-01-07 - Dan Bode <dan@puppetlabs.com> - 0.10.0
+ * Add purging support to ini file (2f22483)
+
+##2013-02-05 - James Sweeny <james.sweeny@puppetlabs.com> - 0.10.0
+ * Fix test to use correct key_val_parameter (b1aff63)
+
+##2012-11-06 - Chris Price <chris@puppetlabs.com> - 0.10.0
+ * Added license file w/Apache 2.0 license (5e1d203)
+
+##2012-11-02 - Chris Price <chris@puppetlabs.com> - 0.9.0
+ * Version 0.9.0 released
+
+##2012-10-26 - Chris Price <chris@puppetlabs.com> - 0.9.0
+ * Add detection for commented versions of settings (a45ab65)
+
+##2012-10-20 - Chris Price <chris@puppetlabs.com> - 0.9.0
+ * Refactor to clarify implementation of `save` (f0d443f)
+
+##2012-10-20 - Chris Price <chris@puppetlabs.com> - 0.9.0
+ * Add example for `ensure=absent` (e517148)
+
+##2012-10-20 - Chris Price <chris@puppetlabs.com> - 0.9.0
+ * Better handling of whitespace lines at ends of sections (845fa70)
+
+##2012-10-20 - Chris Price <chris@puppetlabs.com> - 0.9.0
+ * Respect indentation / spacing for existing sections and settings (c2c26de)
+
+##2012-10-17 - Chris Price <chris@puppetlabs.com> - 0.9.0
+ * Minor tweaks to handling of removing settings (cda30a6)
+
+##2012-10-10 - Dan Bode <dan@puppetlabs.com> - 0.9.0
+ * Add support for removing lines (1106d70)
+
+##2012-10-02 - Dan Bode <dan@puppetlabs.com> - 0.9.0
+ * Make value a property (cbc90d3)
+
+##2012-10-02 - Dan Bode <dan@puppetlabs.com> - 0.9.0
+ * Make ruby provider a better parent. (1564c47)
+
+##2012-09-29 - Reid Vandewiele <reid@puppetlabs.com> - 0.9.0
+ * Allow values with spaces to be parsed and set (3829e20)
+
+##2012-09-24 - Chris Price <chris@pupppetlabs.com> - 0.0.3
+ * Version 0.0.3 released
+
+##2012-09-20 - Chris Price <chris@puppetlabs.com> - 0.0.3
+ * Add validation for key_val_separator (e527908)
+
+##2012-09-19 - Chris Price <chris@puppetlabs.com> - 0.0.3
+ * Allow overriding separator string between key/val pairs (8d1fdc5)
+
+##2012-08-20 - Chris Price <chris@pupppetlabs.com> - 0.0.2
+ * Version 0.0.2 released
+
+##2012-08-17 - Chris Price <chris@pupppetlabs.com> - 0.0.2
+ * Add support for "global" section at beginning of file (c57dab4)
diff --git a/3rdparty/modules/inifile/CONTRIBUTING.md b/3rdparty/modules/inifile/CONTRIBUTING.md
new file mode 100644 (file)
index 0000000..f1cbde4
--- /dev/null
@@ -0,0 +1,220 @@
+Checklist (and a short version for the impatient)
+=================================================
+
+  * Commits:
+
+    - Make commits of logical units.
+
+    - Check for unnecessary whitespace with "git diff --check" before
+      committing.
+
+    - Commit using Unix line endings (check the settings around "crlf" in
+      git-config(1)).
+
+    - Do not check in commented out code or unneeded files.
+
+    - The first line of the commit message should be a short
+      description (50 characters is the soft limit, excluding ticket
+      number(s)), and should skip the full stop.
+
+    - Associate the issue in the message. The first line should include
+      the issue number in the form "(#XXXX) Rest of message".
+
+    - The body should provide a meaningful commit message, which:
+
+      - uses the imperative, present tense: "change", not "changed" or
+        "changes".
+
+      - includes motivation for the change, and contrasts its
+        implementation with the previous behavior.
+
+    - Make sure that you have tests for the bug you are fixing, or
+      feature you are adding.
+
+    - Make sure the test suites passes after your commit:
+      `bundle exec rspec spec/acceptance` More information on [testing](#Testing) below
+
+    - When introducing a new feature, make sure it is properly
+      documented in the README.md
+
+  * Submission:
+
+    * Pre-requisites:
+
+      - Make sure you have a [GitHub account](https://github.com/join)
+
+      - [Create a ticket](https://tickets.puppetlabs.com/secure/CreateIssue!default.jspa), or [watch the ticket](https://tickets.puppetlabs.com/browse/) you are patching for.
+
+    * Preferred method:
+
+      - Fork the repository on GitHub.
+
+      - Push your changes to a topic branch in your fork of the
+        repository. (the format ticket/1234-short_description_of_change is
+        usually preferred for this project).
+
+      - Submit a pull request to the repository in the puppetlabs
+        organization.
+
+The long version
+================
+
+  1.  Make separate commits for logically separate changes.
+
+      Please break your commits down into logically consistent units
+      which include new or changed tests relevant to the rest of the
+      change.  The goal of doing this is to make the diff easier to
+      read for whoever is reviewing your code.  In general, the easier
+      your diff is to read, the more likely someone will be happy to
+      review it and get it into the code base.
+
+      If you are going to refactor a piece of code, please do so as a
+      separate commit from your feature or bug fix changes.
+
+      We also really appreciate changes that include tests to make
+      sure the bug is not re-introduced, and that the feature is not
+      accidentally broken.
+
+      Describe the technical detail of the change(s).  If your
+      description starts to get too long, that is a good sign that you
+      probably need to split up your commit into more finely grained
+      pieces.
+
+      Commits which plainly describe the things which help
+      reviewers check the patch and future developers understand the
+      code are much more likely to be merged in with a minimum of
+      bike-shedding or requested changes.  Ideally, the commit message
+      would include information, and be in a form suitable for
+      inclusion in the release notes for the version of Puppet that
+      includes them.
+
+      Please also check that you are not introducing any trailing
+      whitespace or other "whitespace errors".  You can do this by
+      running "git diff --check" on your changes before you commit.
+
+  2.  Sending your patches
+
+      To submit your changes via a GitHub pull request, we _highly_
+      recommend that you have them on a topic branch, instead of
+      directly on "master".
+      It makes things much easier to keep track of, especially if
+      you decide to work on another thing before your first change
+      is merged in.
+
+      GitHub has some pretty good
+      [general documentation](http://help.github.com/) on using
+      their site.  They also have documentation on
+      [creating pull requests](http://help.github.com/send-pull-requests/).
+
+      In general, after pushing your topic branch up to your
+      repository on GitHub, you can switch to the branch in the
+      GitHub UI and click "Pull Request" towards the top of the page
+      in order to open a pull request.
+
+
+  3.  Update the related GitHub issue.
+
+      If there is a GitHub issue associated with the change you
+      submitted, then you should update the ticket to include the
+      location of your branch, along with any other commentary you
+      may wish to make.
+
+Testing
+=======
+
+Getting Started
+---------------
+
+Our puppet modules provide [`Gemfile`](./Gemfile)s which can tell a ruby
+package manager such as [bundler](http://bundler.io/) what Ruby packages,
+or Gems, are required to build, develop, and test this software.
+
+Please make sure you have [bundler installed](http://bundler.io/#getting-started)
+on your system, then use it to install all dependencies needed for this project,
+by running
+
+```shell
+% bundle install
+Fetching gem metadata from https://rubygems.org/........
+Fetching gem metadata from https://rubygems.org/..
+Using rake (10.1.0)
+Using builder (3.2.2)
+-- 8><-- many more --><8 --
+Using rspec-system-puppet (2.2.0)
+Using serverspec (0.6.3)
+Using rspec-system-serverspec (1.0.0)
+Using bundler (1.3.5)
+Your bundle is complete!
+Use `bundle show [gemname]` to see where a bundled gem is installed.
+```
+
+NOTE some systems may require you to run this command with sudo.
+
+If you already have those gems installed, make sure they are up-to-date:
+
+```shell
+% bundle update
+```
+
+With all dependencies in place and up-to-date we can now run the tests:
+
+```shell
+% rake spec
+```
+
+This will execute all the [rspec tests](http://rspec-puppet.com/) tests
+under [spec/defines](./spec/defines), [spec/classes](./spec/classes),
+and so on. rspec tests may have the same kind of dependencies as the
+module they are testing. While the module defines in its [Modulefile](./Modulefile),
+rspec tests define them in [.fixtures.yml](./fixtures.yml).
+
+Some puppet modules also come with [beaker](https://github.com/puppetlabs/beaker)
+tests. These tests spin up a virtual machine under
+[VirtualBox](https://www.virtualbox.org/)) with, controlling it with
+[Vagrant](http://www.vagrantup.com/) to actually simulate scripted test
+scenarios. In order to run these, you will need both of those tools
+installed on your system.
+
+You can run them by issuing the following command
+
+```shell
+% rake spec_clean
+% rspec spec/acceptance
+```
+
+This will now download a pre-fabricated image configured in the [default node-set](./spec/acceptance/nodesets/default.yml),
+install puppet, copy this module and install its dependencies per [spec/spec_helper_acceptance.rb](./spec/spec_helper_acceptance.rb)
+and then run all the tests under [spec/acceptance](./spec/acceptance).
+
+Writing Tests
+-------------
+
+XXX getting started writing tests.
+
+If you have commit access to the repository
+===========================================
+
+Even if you have commit access to the repository, you will still need to
+go through the process above, and have someone else review and merge
+in your changes.  The rule is that all changes must be reviewed by a
+developer on the project (that did not write the code) to ensure that
+all changes go through a code review process.
+
+Having someone other than the author of the topic branch recorded as
+performing the merge is the record that they performed the code
+review.
+
+
+Additional Resources
+====================
+
+* [Getting additional help](http://puppetlabs.com/community/get-help)
+
+* [Writing tests](http://projects.puppetlabs.com/projects/puppet/wiki/Development_Writing_Tests)
+
+* [Patchwork](https://patchwork.puppetlabs.com)
+
+* [General GitHub documentation](http://help.github.com/)
+
+* [GitHub pull request documentation](http://help.github.com/send-pull-requests/)
+
diff --git a/3rdparty/modules/inifile/Gemfile b/3rdparty/modules/inifile/Gemfile
new file mode 100644 (file)
index 0000000..2b1b7cd
--- /dev/null
@@ -0,0 +1,47 @@
+source ENV['GEM_SOURCE'] || "https://rubygems.org"
+
+def location_for(place, fake_version = nil)
+  if place =~ /^(git:[^#]*)#(.*)/
+    [fake_version, { :git => $1, :branch => $2, :require => false }].compact
+  elsif place =~ /^file:\/\/(.*)/
+    ['>= 0', { :path => File.expand_path($1), :require => false }]
+  else
+    [place, { :require => false }]
+  end
+end
+
+group :development, :unit_tests do
+  gem 'rspec-core', '3.1.7',     :require => false
+  gem 'puppetlabs_spec_helper',  :require => false
+  gem 'simplecov',               :require => false
+  gem 'puppet_facts',            :require => false
+  gem 'json',                    :require => false
+end
+
+group :system_tests do
+  if beaker_version = ENV['BEAKER_VERSION']
+    gem 'beaker', *location_for(beaker_version)
+  end
+  if beaker_rspec_version = ENV['BEAKER_RSPEC_VERSION']
+    gem 'beaker-rspec', *location_for(beaker_rspec_version)
+  else
+    gem 'beaker-rspec',  :require => false
+  end
+  gem 'serverspec',    :require => false
+end
+
+
+
+if facterversion = ENV['FACTER_GEM_VERSION']
+  gem 'facter', facterversion, :require => false
+else
+  gem 'facter', :require => false
+end
+
+if puppetversion = ENV['PUPPET_GEM_VERSION']
+  gem 'puppet', puppetversion, :require => false
+else
+  gem 'puppet', :require => false
+end
+
+# vim:ft=ruby
diff --git a/3rdparty/modules/inifile/LICENSE b/3rdparty/modules/inifile/LICENSE
new file mode 100644 (file)
index 0000000..73caeda
--- /dev/null
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!) The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright 2012 Chris Price
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/3rdparty/modules/inifile/README.markdown b/3rdparty/modules/inifile/README.markdown
new file mode 100644 (file)
index 0000000..80e8743
--- /dev/null
@@ -0,0 +1,267 @@
+#inifile
+
+[![Build Status](https://travis-ci.org/puppetlabs/puppetlabs-inifile.png?branch=master)](https://travis-ci.org/puppetlabs/puppetlabs-inifile)
+
+####Table of Contents
+
+1. [Overview](#overview)
+2. [Module Description - What the module does and why it is useful](#module-description)
+3. [Setup - The basics of getting started with inifile module](#setup)
+    * [Beginning with inifile](#beginning-with-inifile)
+4. [Usage - Configuration options and additional functionality](#usage)
+5. [Reference - An under-the-hood peek at what the module is doing and how](#reference)
+5. [Limitations - OS compatibility, etc.](#limitations)
+6. [Development - Guide for contributing to the module](#development)
+
+##Overview
+
+The inifile module lets Puppet manage settings stored in INI-style configuration files.
+
+##Module Description
+
+Many applications use INI-style configuration files to store their settings. This module supplies two custom resource types to let you manage those settings through Puppet.
+
+##Setup
+
+###Beginning with inifile
+
+
+To manage a single setting in an INI file, add the `ini_setting` type to a class:
+
+~~~
+ini_setting { "sample setting":
+  ensure  => present,
+  path    => '/tmp/foo.ini',
+  section => 'bar',
+  setting => 'baz',
+  value   => 'quux',
+}
+~~~
+
+##Usage
+
+
+The inifile module tries hard not to manipulate your file any more than it needs to. In most cases, it doesn't affect the original whitespace, comments, ordering, etc.
+
+ * Supports comments starting with either '#' or ';'.
+ * Supports either whitespace or no whitespace around '='.
+ * Adds any missing sections to the INI file.
+
+###Manage multiple values in a setting
+
+Use the `ini_subsetting` type:
+
+~~~
+JAVA_ARGS="-Xmx192m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/pe-puppetdb/puppetdb-oom.hprof "
+
+ini_subsetting {'sample subsetting':
+  ensure            => present,
+  section           => '',
+  key_val_separator => '=',
+  path              => '/etc/default/pe-puppetdb',
+  setting           => 'JAVA_ARGS',
+  subsetting        => '-Xmx',
+  value             => '512m',
+}
+~~~
+
+###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
+
+
+You might want to create child providers that inherit the `ini_setting` provider, for one or both of these purposes:
+
+ * Make a custom resource to manage an application that stores its settings in INI files, without recreating the code to manage the files themselves.
+
+ * [Purge all unmanaged settings](https://docs.puppetlabs.com/references/latest/type.html#resources-attribute-purge) from a managed INI file.
+
+To implement child providers, first specify a custom type. Have it implement a namevar called `name` and a property called `value`:
+
+~~~
+#my_module/lib/puppet/type/glance_api_config.rb
+Puppet::Type.newtype(:glance_api_config) do
+  ensurable
+  newparam(:name, :namevar => true) do
+    desc 'Section/setting name to manage from glance-api.conf'
+    # namevar should be of the form section/setting
+    newvalues(/\S+\/\S+/)
+  end
+  newproperty(:value) do
+    desc 'The value of the setting to define'
+    munge do |v|
+      v.to_s.strip
+    end
+  end
+end
+~~~
+
+Your type also needs a provider that uses the `ini_setting` provider as its parent:
+
+~~~
+# my_module/lib/puppet/provider/glance_api_config/ini_setting.rb
+Puppet::Type.type(:glance_api_config).provide(
+  :ini_setting,
+  # set ini_setting as the parent provider
+  :parent => Puppet::Type.type(:ini_setting).provider(:ruby)
+) do
+  # implement section as the first part of the namevar
+  def section
+    resource[:name].split('/', 2).first
+  end
+  def setting
+    # implement setting as the second part of the namevar
+    resource[:name].split('/', 2).last
+  end
+  # hard code the file path (this allows purging)
+  def self.file_path
+    '/etc/glance/glance-api.conf'
+  end
+end
+~~~
+
+Now the settings in /etc/glance/glance-api.conf file can be managed as individual resources:
+
+~~~
+glance_api_config { 'HEADER/important_config':
+  value => 'secret_value',
+}
+~~~
+
+If you've implemented self.file_path, you can have Puppet purge the file of all lines that aren't implemented as Puppet resources:
+
+~~~
+resources { 'glance_api_config'
+  purge => true,
+}
+~~~
+
+##Reference
+
+###Public Types
+
+ * [`ini_setting`](#type-ini_setting)
+
+ * [`ini_subsetting`](#type-ini_subsetting)
+
+### Type: ini_setting
+
+Manages a setting within an INI file.
+
+#### Parameters
+
+##### `ensure`
+
+Determines whether the specified setting should exist. Valid options: 'present' and 'absent'. Default value: 'present'.
+
+##### `key_val_separator`
+
+*Optional.* Specifies a string to use between each setting name and value (e.g., to determine whether the separator includes whitespace). Valid options: a string. Default value: ' = '.
+
+##### `name`
+
+*Optional.* Specifies an arbitrary name to identify the resource. Valid options: a string. Default value: the title of your declared resource.
+
+##### `path`
+
+*Required.* Specifies an INI file containing the setting to manage. Valid options: a string containing an absolute path.
+
+##### `section`
+
+*Required.* Designates a section of the specified INI file containing the setting to manage. To manage a global setting (at the beginning of the file, before any named sections) enter "". Valid options: a string.
+
+##### `setting`
+
+*Optional.* Designates a section of the specified INI file containing the setting to manage. To manage a global setting (at the beginning of the file, before any named sections) enter "". Defaults to "". Valid options: a string.
+
+##### `value`
+
+*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
+
+
+Manages multiple values within the same INI setting.
+
+#### Parameters
+
+##### `ensure`
+
+Specifies whether the subsetting should be present. Valid options: 'present' and 'absent'. Default value: 'present'.
+
+##### `key_val_separator`
+
+*Optional.* Specifies a string to use between subsetting name and value (e.g., to determine whether the separator includes whitespace). Valid options: a string. Default value: ' = '.
+
+##### `path`
+
+*Required.* Specifies an INI file containing the subsetting to manage. Valid options: a string containing an absolute path.
+
+##### `quote_char`
+
+*Optional.* The character used to quote the entire value of the setting. Valid values are '', '"', and "'". Defaults to ''. Valid options: '', '"' and "'". Default value: ''.
+
+##### `section`
+
+*Optional.* Designates a section of the specified INI file containing the setting to manage. To manage a global setting (at the beginning of the file, before any named sections) enter "". Defaults to "". Valid options: a string.
+
+##### `setting`
+
+*Required.* Designates a setting within the specified section containing the subsetting to manage. Valid options: a string.
+
+##### `subsetting`
+
+*Required.* Designates a subsetting to manage within the specified setting. Valid options: a string.
+
+
+##### `subsetting_separator`
+
+*Optional.* Specifies a string to use between subsettings. Valid options: a string. Default value: " ".
+
+##### `value`
+
+*Optional.* Supplies a value for the specified subsetting. Valid options: a string. Default value: undefined.
+
+##Limitations
+
+This module has been tested on [all PE-supported platforms](https://forge.puppetlabs.com/supported#compat-matrix), and no issues have been identified. Additionally, it is tested (but not supported) on Windows 7 and Mac OS X 10.9.
+
+##Development
+
+#Development
+
+Puppet Labs modules on the Puppet Forge are open projects, and community contributions are essential for keeping them great. We can't access the huge number of platforms and myriad of hardware, software, and deployment configurations that Puppet is intended to serve.
+
+We want to keep it as easy as possible to contribute changes so that our modules work in your environment. There are a few guidelines that we need contributors to follow so that we can have a chance of keeping on top of things.
+
+For more information, see our [module contribution guide.](https://docs.puppetlabs.com/forge/contributing.html)
+
+###Contributors
+
+To see who's already involved, see the [list of contributors.](https://github.com/puppetlabs/puppetlabs-inifile/graphs/contributors)
diff --git a/3rdparty/modules/inifile/Rakefile b/3rdparty/modules/inifile/Rakefile
new file mode 100644 (file)
index 0000000..181157e
--- /dev/null
@@ -0,0 +1,10 @@
+require 'puppetlabs_spec_helper/rake_tasks'
+require 'puppet-lint/tasks/puppet-lint'
+
+PuppetLint.configuration.fail_on_warnings = true
+PuppetLint.configuration.send('relative')
+PuppetLint.configuration.send('disable_80chars')
+PuppetLint.configuration.send('disable_class_inherits_from_params_class')
+PuppetLint.configuration.send('disable_documentation')
+PuppetLint.configuration.send('disable_single_quote_string_with_variables')
+PuppetLint.configuration.ignore_paths = ["spec/**/*.pp", "pkg/**/*.pp"]
diff --git a/3rdparty/modules/inifile/checksums.json b/3rdparty/modules/inifile/checksums.json
new file mode 100644 (file)
index 0000000..38b6ed9
--- /dev/null
@@ -0,0 +1,53 @@
+{
+  "CHANGELOG.md": "d1972a553041358de48fa37f684899b3",
+  "CONTRIBUTING.md": "e2b8e8e433fc76b3798b7fe435f49375",
+  "Gemfile": "e62c96457cdaab2a09f1a37479ea6351",
+  "LICENSE": "519b25a3992e0598a9855e4ccd7f66a1",
+  "README.markdown": "66359672ea53606b5f71dc6b9ed98e2a",
+  "Rakefile": "d953eb985f82600dc3b9ac6e1f2cfe64",
+  "lib/puppet/parser/functions/create_ini_settings.rb": "c5d2c4531f93395ce0e6c604a816a0bb",
+  "lib/puppet/provider/ini_setting/ruby.rb": "194c03eab6111e5eb6668ee847cdabcf",
+  "lib/puppet/provider/ini_subsetting/ruby.rb": "a5081f6220da11fa043fdcc5c9fd2a08",
+  "lib/puppet/type/ini_setting.rb": "267e14296a7455a68487b2004734205c",
+  "lib/puppet/type/ini_subsetting.rb": "09e14581b19a1a0f2180c715207a3e12",
+  "lib/puppet/util/external_iterator.rb": "69ad1eb930ca6d8d6b6faea343b4a22e",
+  "lib/puppet/util/ini_file/section.rb": "77757399ed9b9ce352ddcc8b8f9273c4",
+  "lib/puppet/util/ini_file.rb": "738a29a32ee6a0adb0a2e4291a3571c9",
+  "lib/puppet/util/setting_value.rb": "a649418f4c767d976f4bf13985575b3c",
+  "metadata.json": "8d8a3cfa6d0b1d6e5935b4cd4bf09a55",
+  "spec/acceptance/ini_setting_spec.rb": "3cc7535332c5d5f063516a432a2790a7",
+  "spec/acceptance/ini_subsetting_spec.rb": "382294494288a6a064f05cb05f878161",
+  "spec/acceptance/nodesets/centos-510-x64.yml": "5698f7e61292730c603e03f64fe19359",
+  "spec/acceptance/nodesets/centos-59-x64.yml": "57eb3e471b9042a8ea40978c467f8151",
+  "spec/acceptance/nodesets/centos-64-x64-pe.yml": "ec075d95760df3d4702abea1ce0a829b",
+  "spec/acceptance/nodesets/centos-64-x64.yml": "9cde7b5d2ab6a42366d2344c264d6bdc",
+  "spec/acceptance/nodesets/centos-65-x64.yml": "3e5c36e6aa5a690229e720f4048bb8af",
+  "spec/acceptance/nodesets/debian-607-x64.yml": "d566bf76f534e2af7c9a4605316d232c",
+  "spec/acceptance/nodesets/debian-73-x64.yml": "ba5a75e27644c48ad8f3564fb6d372a7",
+  "spec/acceptance/nodesets/default.yml": "9cde7b5d2ab6a42366d2344c264d6bdc",
+  "spec/acceptance/nodesets/fedora-18-x64.yml": "acc126fa764c39a3b1df36e9224a21d9",
+  "spec/acceptance/nodesets/sles-11sp1-x64.yml": "fa0046bd89c1ab4ba9521ad79db234cd",
+  "spec/acceptance/nodesets/ubuntu-server-10044-x64.yml": "75e86400b7889888dc0781c0ae1a1297",
+  "spec/acceptance/nodesets/ubuntu-server-12042-x64.yml": "d30d73e34cd50b043c7d14e305955269",
+  "spec/acceptance/nodesets/ubuntu-server-1404-x64.yml": "5f0aed10098ac5b78e4217bb27c7aaf0",
+  "spec/acceptance/nodesets/windows-2003-i386.yml": "ee44e67756ecd0c07e08ae8ec91684cd",
+  "spec/acceptance/nodesets/windows-2003r2-x86_64.yml": "23ae971a41c6542ebbed1a36d36f6586",
+  "spec/acceptance/nodesets/windows-2008-x86_64.yml": "9d522b6a787076a2310e22ce020c07bf",
+  "spec/acceptance/nodesets/windows-2008r2-x86_64.yml": "eb61cf0d5c236ec2563d90ad8156a582",
+  "spec/acceptance/nodesets/windows-2012-x86_64.yml": "a5b9f55bff9c6b368a5a6850a6639ac2",
+  "spec/acceptance/nodesets/windows-2012r2-x86_64.yml": "5056f11909ee24215a7fac0729081307",
+  "spec/classes/create_ini_settings_test_spec.rb": "9f21c2817edeafaaac204773500a8783",
+  "spec/classes/inherit_test1_spec.rb": "56bbfd63e770b180abc3fd7e331de2fb",
+  "spec/functions/create_ini_settings_spec.rb": "5a7c29d3d85021a4dd49011d5420ba54",
+  "spec/spec.opts": "a600ded995d948e393fbe2320ba8e51c",
+  "spec/spec_helper.rb": "1b09547c3e8324897a9e13ea5a78916c",
+  "spec/spec_helper_acceptance.rb": "fc9948f34ea6b37f9e9b74c485989f21",
+  "spec/unit/puppet/provider/ini_setting/inheritance_spec.rb": "bbe2fb9d6805ae8cae85271e48f646b3",
+  "spec/unit/puppet/provider/ini_setting/ruby_spec.rb": "02366fbb824705394815b9b014c0521f",
+  "spec/unit/puppet/provider/ini_subsetting/ruby_spec.rb": "b05cf15a5830feb249ad7177f7d966ca",
+  "spec/unit/puppet/util/external_iterator_spec.rb": "35cc6e56e0064e496e9151dd778f751f",
+  "spec/unit/puppet/util/ini_file_spec.rb": "7c9845cfb384ee68ef03f296158343f1",
+  "spec/unit/puppet/util/setting_value_spec.rb": "535abf7d56dc2d5492df637382cef3c5",
+  "tests/ini_setting.pp": "9c8a9d2c453901cedb106cada253f1f6",
+  "tests/ini_subsetting.pp": "71c82234fa8bb8cb442ff01436ce2cf3"
+}
\ No newline at end of file
diff --git a/3rdparty/modules/inifile/lib/puppet/parser/functions/create_ini_settings.rb b/3rdparty/modules/inifile/lib/puppet/parser/functions/create_ini_settings.rb
new file mode 100644 (file)
index 0000000..8e14591
--- /dev/null
@@ -0,0 +1,86 @@
+#
+# create_ini_settings.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:create_ini_settings, :type => :statement, :doc => <<-EOS
+Uses create_resources to create a set of ini_setting resources from a hash:
+
+    $settings = {  section1 => {
+        setting1 => val1
+      },
+      section2 => {
+        setting2 => val2,
+        setting3 => {
+          ensure => absent
+        }
+      }
+    }
+    $defaults = {
+      path => '/tmp/foo.ini'
+    }
+    create_ini_settings($settings,$defaults)
+
+
+Will create the following resources
+
+    ini_setting{'[section1] setting1':
+      ensure  => present,
+      section => 'section1',
+      setting => 'setting1',
+      value   => 'val1',
+      path    => '/tmp/foo.ini',
+    }
+    ini_setting{'[section2] setting2':
+      ensure  => present,
+      section => 'section2',
+      setting => 'setting2',
+      value   => 'val2',
+      path    => '/tmp/foo.ini',
+    }
+    ini_setting{'[section2] setting3':
+      ensure  => absent,
+      section => 'section2',
+      setting => 'setting3',
+      path    => '/tmp/foo.ini',
+    }
+
+EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, "create_ini_settings(): Wrong number of arguments " +
+      "given (#{arguments.size} for 1 or 2)") unless arguments.size.between?(1,2)
+
+    settings = arguments[0]
+    defaults = arguments[1] || {}
+
+    if [settings,defaults].any?{|i| !i.is_a?(Hash) }
+      raise(Puppet::ParseError,
+        'create_ini_settings(): Requires all arguments to be a Hash')
+    end
+
+    resources = settings.keys.inject({}) do |res, section|
+      raise(Puppet::ParseError,
+        "create_ini_settings(): Section #{section} must contain a Hash") \
+        unless settings[section].is_a?(Hash)
+
+      settings[section].each do |setting, value|
+        res["[#{section}] #{setting}"] = {
+          'ensure'  => 'present',
+          'section' => section,
+          'setting' => setting,
+        }.merge(if value.is_a?(Hash)
+          value
+        else
+          { 'value'   => value, }
+        end)
+      end
+      res
+    end
+
+    Puppet::Parser::Functions.function('create_resources')
+    function_create_resources(['ini_setting',resources,defaults])
+  end
+end
+
+# vim: set ts=2 sw=2 et :
diff --git a/3rdparty/modules/inifile/lib/puppet/provider/ini_setting/ruby.rb b/3rdparty/modules/inifile/lib/puppet/provider/ini_setting/ruby.rb
new file mode 100644 (file)
index 0000000..2455541
--- /dev/null
@@ -0,0 +1,118 @@
+require File.expand_path('../../../util/ini_file', __FILE__)
+
+Puppet::Type.type(:ini_setting).provide(:ruby) do
+
+  def self.instances
+    # this code is here to support purging and the query-all functionality of the
+    # 'puppet resource' command, on a per-file basis.  Users
+    # can create a type for a specific config file with a provider that uses
+    # this as its parent and implements the method
+    # 'self.file_path', and that will provide the value for the path to the
+    # ini file (rather than needing to specify it on each ini setting
+    # declaration).  This allows 'purging' to be used to clear out
+    # all settings from a particular ini file except those included in
+    # the catalog.
+    if self.respond_to?(:file_path)
+      # figure out what to do about the seperator
+      ini_file  = Puppet::Util::IniFile.new(file_path, '=')
+      resources = []
+      ini_file.section_names.each do |section_name|
+        ini_file.get_settings(section_name).each do |setting, value|
+          resources.push(
+            new(
+              :name   => namevar(section_name, setting),
+              :value  => value,
+              :ensure => :present
+            )
+          )
+        end
+      end
+      resources
+    else
+      raise(Puppet::Error, 'Ini_settings only support collecting instances when a file path is hard coded')
+    end
+  end
+
+  def self.namevar(section_name, setting)
+    "#{section_name}/#{setting}"
+  end
+
+  def exists?
+    !ini_file.get_value(section, setting).nil?
+  end
+
+  def create
+    ini_file.set_value(section, setting, resource[:value])
+    ini_file.save
+    @ini_file = nil
+  end
+
+  def destroy
+    ini_file.remove_setting(section, setting)
+    ini_file.save
+    @ini_file = nil
+  end
+
+  def value
+    ini_file.get_value(section, setting)
+  end
+
+  def value=(value)
+    ini_file.set_value(section, setting, resource[:value])
+    ini_file.save
+  end
+
+  def section
+    # this method is here so that it can be overridden by a child provider
+    resource[:section]
+  end
+
+  def setting
+    # this method is here so that it can be overridden by a child provider
+    resource[:setting]
+  end
+
+  def file_path
+    # this method is here to support purging and sub-classing.
+    # if a user creates a type and subclasses our provider and provides a
+    # 'file_path' method, then they don't have to specify the
+    # path as a parameter for every ini_setting declaration.
+    # This implementation allows us to support that while still
+    # falling back to the parameter value when necessary.
+    if self.class.respond_to?(:file_path)
+      self.class.file_path
+    else
+      resource[:path]
+    end
+  end
+
+  def separator
+    if resource.class.validattr?(:key_val_separator)
+      resource[:key_val_separator] || '='
+    else
+      '='
+    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, section_prefix, section_suffix)
+  end
+
+end
diff --git a/3rdparty/modules/inifile/lib/puppet/provider/ini_subsetting/ruby.rb b/3rdparty/modules/inifile/lib/puppet/provider/ini_subsetting/ruby.rb
new file mode 100644 (file)
index 0000000..764124d
--- /dev/null
@@ -0,0 +1,73 @@
+require File.expand_path('../../../util/ini_file', __FILE__)
+require File.expand_path('../../../util/setting_value', __FILE__)
+
+Puppet::Type.type(:ini_subsetting).provide(:ruby) do
+
+  def exists?
+    setting_value.get_subsetting_value(subsetting)
+  end
+
+  def create
+    setting_value.add_subsetting(subsetting, resource[:value])
+    ini_file.set_value(section, setting, setting_value.get_value)
+    ini_file.save
+    @ini_file = nil
+    @setting_value = nil
+  end
+
+  def destroy
+    setting_value.remove_subsetting(subsetting)
+    ini_file.set_value(section, setting, setting_value.get_value)
+    ini_file.save
+    @ini_file = nil
+    @setting_value = nil
+  end
+
+  def value
+    setting_value.get_subsetting_value(subsetting)
+  end
+
+  def value=(value)
+    setting_value.add_subsetting(subsetting, resource[:value])
+    ini_file.set_value(section, setting, setting_value.get_value)
+    ini_file.save
+  end
+
+  def section
+    resource[:section]
+  end
+
+  def setting
+    resource[:setting]
+  end
+
+  def subsetting
+    resource[:subsetting]
+  end
+
+  def subsetting_separator
+    resource[:subsetting_separator]
+  end
+
+  def file_path
+    resource[:path]
+  end
+
+  def separator
+    resource[:key_val_separator] || '='
+  end
+
+  def quote_char
+    resource[:quote_char]
+  end
+
+  private
+  def ini_file
+    @ini_file ||= Puppet::Util::IniFile.new(file_path, separator)
+  end
+
+  def setting_value
+    @setting_value ||= Puppet::Util::SettingValue.new(ini_file.get_value(section, setting), subsetting_separator, quote_char)
+  end
+
+end
diff --git a/3rdparty/modules/inifile/lib/puppet/type/ini_setting.rb b/3rdparty/modules/inifile/lib/puppet/type/ini_setting.rb
new file mode 100644 (file)
index 0000000..15ae241
--- /dev/null
@@ -0,0 +1,54 @@
+Puppet::Type.newtype(:ini_setting) do
+
+  ensurable do
+    defaultvalues
+    defaultto :present
+  end
+
+  newparam(:name, :namevar => true) do
+    desc 'An arbitrary name used as the identity of the resource.'
+  end
+
+  newparam(:section) do
+    desc 'The name of the section in the ini file in which the setting should be defined.' +
+      'If not provided, defaults to global, top of file, sections.'
+    defaultto("")
+  end
+
+  newparam(:setting) do
+    desc 'The name of the setting to be defined.'
+  end
+
+  newparam(:path) do
+    desc 'The ini file Puppet will ensure contains the specified setting.'
+    validate do |value|
+      unless (Puppet.features.posix? and value =~ /^\//) or (Puppet.features.microsoft_windows? and (value =~ /^.:\// or value =~ /^\/\/[^\/]+\/[^\/]+/))
+        raise(Puppet::Error, "File paths must be fully qualified, not '#{value}'")
+      end
+    end
+  end
+
+  newparam(:key_val_separator) do
+    desc 'The separator string to use between each setting name and value. ' +
+        'Defaults to " = ", but you could use this to override e.g. ": ", or' +
+        'whether or not the separator should include whitespace.'
+    defaultto(" = ")
+  end
+
+  newproperty(:value) do
+    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/3rdparty/modules/inifile/lib/puppet/type/ini_subsetting.rb b/3rdparty/modules/inifile/lib/puppet/type/ini_subsetting.rb
new file mode 100644 (file)
index 0000000..c1d6f08
--- /dev/null
@@ -0,0 +1,63 @@
+Puppet::Type.newtype(:ini_subsetting) do
+
+  ensurable do
+    defaultvalues
+    defaultto :present
+  end
+
+  newparam(:name, :namevar => true) do
+    desc 'An arbitrary name used as the identity of the resource.'
+  end
+
+  newparam(:section) do
+    desc 'The name of the section in the ini file in which the setting should be defined.' +
+      'If not provided, defaults to global, top of file, sections.'
+    defaultto("")
+  end
+
+  newparam(:setting) do
+    desc 'The name of the setting to be defined.'
+  end
+
+  newparam(:subsetting) do
+    desc 'The name of the subsetting to be defined.'
+  end
+
+  newparam(:subsetting_separator) do
+    desc 'The separator string between subsettings. Defaults to " "'
+    defaultto(" ")
+  end
+
+  newparam(:path) do
+    desc 'The ini file Puppet will ensure contains the specified setting.'
+    validate do |value|
+      unless (Puppet.features.posix? and value =~ /^\//) or (Puppet.features.microsoft_windows? and (value =~ /^.:\// or value =~ /^\/\/[^\/]+\/[^\/]+/))
+        raise(Puppet::Error, "File paths must be fully qualified, not '#{value}'")
+      end
+    end
+  end
+
+  newparam(:key_val_separator) do
+    desc 'The separator string to use between each setting name and value. ' +
+        'Defaults to " = ", but you could use this to override e.g. ": ", or' +
+        'whether or not the separator should include whitespace.'
+    defaultto(" = ")
+  end
+
+  newparam(:quote_char) do
+    desc 'The character used to quote the entire value of the setting. ' +
+        %q{Valid values are '', '"' and "'". Defaults to ''.}
+    defaultto('')
+
+    validate do |value|
+      unless value =~ /^["']?$/
+        raise Puppet::Error, %q{:quote_char valid values are '', '"' and "'"}
+      end
+    end
+  end
+
+  newproperty(:value) do
+    desc 'The value of the subsetting to be defined.'
+  end
+
+end
diff --git a/3rdparty/modules/inifile/lib/puppet/util/external_iterator.rb b/3rdparty/modules/inifile/lib/puppet/util/external_iterator.rb
new file mode 100644 (file)
index 0000000..45c0fa4
--- /dev/null
@@ -0,0 +1,28 @@
+module Puppet
+module Util
+  class ExternalIterator
+    def initialize(coll)
+      @coll = coll
+      @cur_index = -1
+    end
+
+    def next
+      @cur_index = @cur_index + 1
+      item_at(@cur_index)
+    end
+
+    def peek
+      item_at(@cur_index + 1)
+    end
+
+    private
+    def item_at(index)
+      if @coll.length > index
+        [@coll[index], index]
+      else
+        [nil, nil]
+      end
+    end
+  end
+end
+end
diff --git a/3rdparty/modules/inifile/lib/puppet/util/ini_file.rb b/3rdparty/modules/inifile/lib/puppet/util/ini_file.rb
new file mode 100644 (file)
index 0000000..e67e5b5
--- /dev/null
@@ -0,0 +1,326 @@
+require File.expand_path('../external_iterator', __FILE__)
+require File.expand_path('../ini_file/section', __FILE__)
+
+module Puppet
+module Util
+  class IniFile
+
+    def initialize(path, key_val_separator = ' = ', section_prefix = '[', section_suffix = ']')
+
+      k_v_s = key_val_separator.strip
+
+      @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*$/
+
+      @path = path
+      @key_val_separator = key_val_separator
+      @section_names = []
+      @sections_hash = {}
+      if File.file?(@path)
+        parse_file
+      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
+
+    def get_settings(section_name)
+      section = @sections_hash[section_name]
+      section.setting_names.inject({}) do |result, setting|
+        result[setting] = section.get_value(setting)
+        result
+      end
+    end
+
+    def get_value(section_name, setting)
+      if (@sections_hash.has_key?(section_name))
+        @sections_hash[section_name].get_value(setting)
+      end
+    end
+
+    def set_value(section_name, setting, value)
+      unless (@sections_hash.has_key?(section_name))
+        add_section(Section.new(section_name, nil, nil, nil, nil))
+      end
+
+      section = @sections_hash[section_name]
+
+      if (section.has_existing_setting?(setting))
+        update_line(section, setting, value)
+        section.update_existing_setting(setting, value)
+      elsif result = find_commented_setting(section, setting)
+        # So, this stanza is a bit of a hack.  What we're trying
+        # to do here is this: for settings that don't already
+        # exist, we want to take a quick peek to see if there
+        # is a commented-out version of them in the section.
+        # If so, we'd prefer to add the setting directly after
+        # the commented line, rather than at the end of the section.
+
+        # If we get here then we found a commented line, so we
+        # call "insert_inline_setting_line" to update the lines array
+        insert_inline_setting_line(result, section, setting, value)
+
+        # Then, we need to tell the setting object that we hacked
+        # in an inline setting
+        section.insert_inline_setting(setting, value)
+
+        # Finally, we need to update all of the start/end line
+        # numbers for all of the sections *after* the one that
+        # was modified.
+        section_index = @section_names.index(section_name)
+        increment_section_line_numbers(section_index + 1)
+      else
+        section.set_additional_setting(setting, value)
+      end
+    end
+
+    def remove_setting(section_name, setting)
+      section = @sections_hash[section_name]
+      if (section.has_existing_setting?(setting))
+        # If the setting is found, we have some work to do.
+        # First, we remove the line from our array of lines:
+        remove_line(section, setting)
+
+        # Then, we need to tell the setting object to remove
+        # the setting from its state:
+        section.remove_existing_setting(setting)
+
+        # Finally, we need to update all of the start/end line
+        # numbers for all of the sections *after* the one that
+        # was modified.
+        section_index = @section_names.index(section_name)
+        decrement_section_line_numbers(section_index + 1)
+      end
+    end
+
+    def save
+      File.open(@path, 'w') do |fh|
+
+        @section_names.each_index do |index|
+          name = @section_names[index]
+
+          section = @sections_hash[name]
+
+          # We need a buffer to cache lines that are only whitespace
+          whitespace_buffer = []
+
+          if (section.is_new_section?) && (! section.is_global?)
+            fh.puts("\n#{@section_prefix}#{section.name}#{@section_suffix}")
+          end
+
+          if ! section.is_new_section?
+            # write all of the pre-existing settings
+            (section.start_line..section.end_line).each do |line_num|
+              line = lines[line_num]
+
+              # We buffer any lines that are only whitespace so that
+              # if they are at the end of a section, we can insert
+              # any new settings *before* the final chunk of whitespace
+              # lines.
+              if (line =~ /^\s*$/)
+                whitespace_buffer << line
+              else
+                # If we get here, we've found a non-whitespace line.
+                # We'll flush any cached whitespace lines before we
+                # write it.
+                flush_buffer_to_file(whitespace_buffer, fh)
+                fh.puts(line)
+              end
+            end
+          end
+
+          # write new settings, if there are any
+          section.additional_settings.each_pair do |key, value|
+            fh.puts("#{' ' * (section.indentation || 0)}#{key}#{@key_val_separator}#{value}")
+          end
+
+          if (whitespace_buffer.length > 0)
+            flush_buffer_to_file(whitespace_buffer, fh)
+          else
+            # We get here if there were no blank lines at the end of the
+            # section.
+            #
+            # If we are adding a new section with a new setting,
+            # and if there are more sections that come after this one,
+            # we'll write one blank line just so that there is a little
+            # whitespace between the sections.
+            #if (section.end_line.nil? &&
+            if (section.is_new_section? &&
+                (section.additional_settings.length > 0) &&
+                (index < @section_names.length - 1))
+              fh.puts("")
+            end
+          end
+
+        end
+      end
+    end
+
+
+    private
+    def add_section(section)
+      @sections_hash[section.name] = section
+      @section_names << section.name
+    end
+
+    def parse_file
+      line_iter = create_line_iter
+
+      # We always create a "global" section at the beginning of the file, for
+      # anything that appears before the first named section.
+      section = read_section('', 0, line_iter)
+      add_section(section)
+      line, line_num = line_iter.next
+
+      while line
+        if (match = @@SECTION_REGEX.match(line))
+          section = read_section(match[1], line_num, line_iter)
+          add_section(section)
+        end
+        line, line_num = line_iter.next
+      end
+    end
+
+    def read_section(name, start_line, line_iter)
+      settings = {}
+      end_line_num = nil
+      min_indentation = nil
+      while true
+        line, line_num = line_iter.peek
+        if (line_num.nil? or match = @@SECTION_REGEX.match(line))
+          return Section.new(name, start_line, end_line_num, settings, min_indentation)
+        elsif (match = @@SETTING_REGEX.match(line))
+          settings[match[2]] = match[4]
+          indentation = match[1].length
+          min_indentation = [indentation, min_indentation || indentation].min
+        end
+        end_line_num = line_num
+        line_iter.next
+      end
+    end
+
+    def update_line(section, setting, value)
+      (section.start_line..section.end_line).each do |line_num|
+        if (match = @@SETTING_REGEX.match(lines[line_num]))
+          if (match[2] == setting)
+            lines[line_num] = "#{match[1]}#{match[2]}#{match[3]}#{value}"
+          end
+        end
+      end
+    end
+
+    def remove_line(section, setting)
+      (section.start_line..section.end_line).each do |line_num|
+        if (match = @@SETTING_REGEX.match(lines[line_num]))
+          if (match[2] == setting)
+            lines.delete_at(line_num)
+          end
+        end
+      end
+    end
+
+    def create_line_iter
+      ExternalIterator.new(lines)
+    end
+
+    def lines
+        @lines ||= IniFile.readlines(@path)
+    end
+
+    # This is mostly here because it makes testing easier--we don't have
+    #  to try to stub any methods on File.
+    def self.readlines(path)
+        # If this type is ever used with very large files, we should
+        #  write this in a different way, using a temp
+        #  file; for now assuming that this type is only used on
+        #  small-ish config files that can fit into memory without
+        #  too much trouble.
+        File.readlines(path)
+    end
+
+    # This utility method scans through the lines for a section looking for
+    # commented-out versions of a setting.  It returns `nil` if it doesn't
+    # find one.  If it does find one, then it returns a hash containing
+    # two keys:
+    #
+    #   :line_num - the line number that contains the commented version
+    #               of the setting
+    #   :match    - the ruby regular expression match object, which can
+    #               be used to mimic the whitespace from the comment line
+    def find_commented_setting(section, setting)
+      return nil if section.is_new_section?
+      (section.start_line..section.end_line).each do |line_num|
+        if (match = @@COMMENTED_SETTING_REGEX.match(lines[line_num]))
+          if (match[3] == setting)
+            return { :match => match, :line_num => line_num }
+          end
+        end
+      end
+      nil
+    end
+
+    # This utility method is for inserting a line into the existing
+    # lines array.  The `result` argument is expected to be in the
+    # format of the return value of `find_commented_setting`.
+    def insert_inline_setting_line(result, section, setting, value)
+      line_num = result[:line_num]
+      match = result[:match]
+      lines.insert(line_num + 1, "#{' ' * (section.indentation || 0 )}#{setting}#{match[4]}#{value}")
+    end
+
+    # Utility method; given a section index (index into the @section_names
+    # array), decrement the start/end line numbers for that section and all
+    # all of the other sections that appear *after* the specified section.
+    def decrement_section_line_numbers(section_index)
+      @section_names[section_index..(@section_names.length - 1)].each do |name|
+        section = @sections_hash[name]
+        section.decrement_line_nums
+      end
+    end
+
+    # Utility method; given a section index (index into the @section_names
+    # array), increment the start/end line numbers for that section and all
+    # all of the other sections that appear *after* the specified section.
+    def increment_section_line_numbers(section_index)
+      @section_names[section_index..(@section_names.length - 1)].each do |name|
+        section = @sections_hash[name]
+        section.increment_line_nums
+      end
+    end
+
+
+    def flush_buffer_to_file(buffer, fh)
+      if buffer.length > 0
+        buffer.each { |l| fh.puts(l) }
+        buffer.clear
+      end
+    end
+
+  end
+end
+end
diff --git a/3rdparty/modules/inifile/lib/puppet/util/ini_file/section.rb b/3rdparty/modules/inifile/lib/puppet/util/ini_file/section.rb
new file mode 100644 (file)
index 0000000..9682d7f
--- /dev/null
@@ -0,0 +1,103 @@
+module Puppet
+module Util
+class IniFile
+  class Section
+    # Some implementation details:
+    #
+    #  * `name` will be set to the empty string for the 'global' section.
+    #  * there will always be a 'global' section, with a `start_line` of 0,
+    #    but if the file actually begins with a real section header on
+    #    the first line, then the 'global' section will have an
+    #    `end_line` of `nil`.
+    #  * `start_line` and `end_line` will be set to `nil` for a new non-global
+    #    section.
+    def initialize(name, start_line, end_line, settings, indentation)
+      @name = name
+      @start_line = start_line
+      @end_line = end_line
+      @existing_settings = settings.nil? ? {} : settings
+      @additional_settings = {}
+      @indentation = indentation
+    end
+
+    attr_reader :name, :start_line, :end_line, :additional_settings, :indentation
+
+    def is_global?()
+      @name == ''
+    end
+
+    def is_new_section?()
+      # a new section (global or named) will always have `end_line`
+      # set to `nil`
+      @end_line.nil?
+    end
+
+    def setting_names
+      @existing_settings.keys | @additional_settings.keys
+    end
+
+    def get_value(setting_name)
+      @existing_settings[setting_name] || @additional_settings[setting_name]
+    end
+
+    def has_existing_setting?(setting_name)
+      @existing_settings.has_key?(setting_name)
+    end
+
+    def update_existing_setting(setting_name, value)
+      @existing_settings[setting_name] = value
+    end
+
+    def remove_existing_setting(setting_name)
+      if (@existing_settings.delete(setting_name))
+        if @end_line
+          @end_line = @end_line - 1
+        end
+      end
+    end
+
+    # This is a hacky method; it's basically called when we need to insert
+    # a new setting but we don't want it to appear at the very end of the
+    # section.  Instead we hack it into the existing settings list and
+    # increment our end_line number--this assumes that the caller (`ini_file`)
+    # is doing some babysitting w/rt the other sections and the actual data
+    # of the lines.
+    def insert_inline_setting(setting_name, value)
+      @existing_settings[setting_name] = value
+      if @end_line
+        @end_line = @end_line + 1
+      end
+    end
+
+    def set_additional_setting(setting_name, value)
+      @additional_settings[setting_name] = value
+    end
+
+    # Decrement the start and end line numbers for the section (if they are
+    # defined); this is intended to be called when a setting is removed
+    # from a section that comes before this section in the ini file.
+    def decrement_line_nums()
+      if @start_line
+        @start_line = @start_line - 1
+      end
+      if @end_line
+        @end_line = @end_line - 1
+      end
+    end
+
+    # Increment the start and end line numbers for the section (if they are
+    # defined); this is intended to be called when an inline setting is added
+    # to a section that comes before this section in the ini file.
+    def increment_line_nums()
+      if @start_line
+        @start_line = @start_line + 1
+      end
+      if @end_line
+        @end_line = @end_line + 1
+      end
+    end
+
+  end
+end
+end
+end
diff --git a/3rdparty/modules/inifile/lib/puppet/util/setting_value.rb b/3rdparty/modules/inifile/lib/puppet/util/setting_value.rb
new file mode 100644 (file)
index 0000000..d44330a
--- /dev/null
@@ -0,0 +1,95 @@
+module Puppet
+module Util
+
+  class SettingValue
+
+    def initialize(setting_value, subsetting_separator = ' ', default_quote_char = nil)
+      @setting_value = setting_value
+      @subsetting_separator = subsetting_separator
+
+      default_quote_char ||= ''
+
+      if @setting_value
+        unquoted, @quote_char = unquote_setting_value(setting_value)
+        @subsetting_items = unquoted.scan(Regexp.new("(?:(?:[^\\#{@subsetting_separator}]|\\.)+)"))  # an item can contain escaped separator
+        @subsetting_items.map! { |item| item.strip }
+        @quote_char = default_quote_char if @quote_char.empty?
+      else
+        @subsetting_items = []
+        @quote_char = default_quote_char
+      end     
+    end
+
+    def unquote_setting_value(setting_value)
+      quote_char = ""
+      if (setting_value.start_with?('"') and setting_value.end_with?('"'))
+        quote_char = '"'
+      elsif (setting_value.start_with?("'") and setting_value.end_with?("'"))
+        quote_char = "'"
+      end
+
+      unquoted = setting_value
+
+      if (quote_char != "")
+        unquoted = setting_value[1, setting_value.length - 2]
+      end
+
+      [unquoted, quote_char]
+    end
+
+    def get_value
+    
+      result = ""
+      first = true
+      
+      @subsetting_items.each { |item|
+        result << @subsetting_separator unless first
+        result << item        
+        first = false
+      }
+      
+      @quote_char + result + @quote_char
+    end
+
+    def get_subsetting_value(subsetting)
+    
+      value = nil
+      
+      @subsetting_items.each { |item|
+        if(item.start_with?(subsetting))
+          value = item[subsetting.length, item.length - subsetting.length]
+          break
+        end
+      }
+      
+      value
+    end
+    
+    def add_subsetting(subsetting, subsetting_value)
+    
+      new_item = subsetting + (subsetting_value || '')
+      found = false
+
+      @subsetting_items.map! { |item|
+        if item.start_with?(subsetting)
+          value = new_item
+          found = true
+        else
+          value = item
+        end
+        
+        value
+      }
+      
+      unless found
+        @subsetting_items.push(new_item)
+      end
+    end
+
+    def remove_subsetting(subsetting)   
+      @subsetting_items = @subsetting_items.map { |item| item.start_with?(subsetting) ? nil : item }.compact
+    end
+    
+  end
+end
+end
diff --git a/3rdparty/modules/inifile/metadata.json b/3rdparty/modules/inifile/metadata.json
new file mode 100644 (file)
index 0000000..b4bff40
--- /dev/null
@@ -0,0 +1,104 @@
+{
+  "name": "puppetlabs-inifile",
+  "version": "1.3.0",
+  "author": "Puppet Labs",
+  "summary": "Resource types for managing settings in INI files",
+  "license": "Apache-2.0",
+  "source": "https://github.com/puppetlabs/puppetlabs-inifile",
+  "project_page": "https://github.com/puppetlabs/puppetlabs-inifile",
+  "issues_url": "https://tickets.puppetlabs.com/browse/MODULES",
+  "dependencies": [
+  
+  ],
+  "operatingsystem_support": [
+    {
+      "operatingsystem": "RedHat",
+      "operatingsystemrelease": [
+        "5",
+        "6",
+        "7"
+      ]
+    },
+    {
+      "operatingsystem": "CentOS",
+      "operatingsystemrelease": [
+        "5",
+        "6",
+        "7"
+      ]
+    },
+    {
+      "operatingsystem": "OracleLinux",
+      "operatingsystemrelease": [
+        "5",
+        "6",
+        "7"
+      ]
+    },
+    {
+      "operatingsystem": "Scientific",
+      "operatingsystemrelease": [
+        "5",
+        "6",
+        "7"
+      ]
+    },
+    {
+      "operatingsystem": "SLES",
+      "operatingsystemrelease": [
+        "10 SP4",
+        "11 SP1",
+        "12"
+      ]
+    },
+    {
+      "operatingsystem": "Debian",
+      "operatingsystemrelease": [
+        "6",
+        "7"
+      ]
+    },
+    {
+      "operatingsystem": "Ubuntu",
+      "operatingsystemrelease": [
+        "10.04",
+        "12.04",
+        "14.04"
+      ]
+    },
+    {
+      "operatingsystem": "Solaris",
+      "operatingsystemrelease": [
+        "10",
+        "11"
+      ]
+    },
+    {
+      "operatingsystem": "Windows",
+      "operatingsystemrelease": [
+        "Server 2003 R2",
+        "Server 2008 R2",
+        "Server 2012",
+        "Server 2012 R2"
+      ]
+    },
+    {
+      "operatingsystem": "AIX",
+      "operatingsystemrelease": [
+        "5.3",
+        "6.1",
+        "7.1"
+      ]
+    }
+  ],
+  "requirements": [
+    {
+      "name": "pe",
+      "version_requirement": "3.x"
+    },
+    {
+      "name": "puppet",
+      "version_requirement": "3.x"
+    }
+  ]
+}
diff --git a/3rdparty/modules/inifile/spec/acceptance/ini_setting_spec.rb b/3rdparty/modules/inifile/spec/acceptance/ini_setting_spec.rb
new file mode 100644 (file)
index 0000000..b7e2b6a
--- /dev/null
@@ -0,0 +1,248 @@
+require 'spec_helper_acceptance'
+
+tmpdir = default.tmpdir('tmp')
+
+describe 'ini_setting resource' do
+  after :all do
+    shell("rm #{tmpdir}/*.ini", :acceptable_exit_codes => [0, 1, 2])
+  end
+
+  shared_examples 'has_content' do |path, pp, content|
+    before :all do
+      shell("rm #{path}", :acceptable_exit_codes => [0, 1, 2])
+    end
+    after :all do
+      shell("cat #{path}", :acceptable_exit_codes => [0, 1, 2])
+      shell("rm #{path}", :acceptable_exit_codes => [0, 1, 2])
+    end
+
+    it 'applies the manifest twice' do
+      apply_manifest(pp, :catch_failures => true)
+      apply_manifest(pp, :catch_changes => true)
+    end
+
+    describe file(path) do
+      it { should be_file }
+      its(:content) { should match content }
+    end
+  end
+
+  shared_examples 'has_error' do |path, pp, error|
+    before :all do
+      shell("rm #{path}", :acceptable_exit_codes => [0, 1, 2])
+    end
+    after :all do
+      shell("cat #{path}", :acceptable_exit_codes => [0, 1, 2])
+      shell("rm #{path}", :acceptable_exit_codes => [0, 1, 2])
+    end
+
+    it 'applies the manifest and gets a failure message' do
+      expect(apply_manifest(pp, :expect_failures => true).stderr).to match(error)
+    end
+
+    describe file(path) do
+      it { should_not be_file }
+    end
+  end
+
+  describe 'ensure parameter' do
+    context '=> present for global and section' do
+      pp = <<-EOS
+      ini_setting { 'ensure => present for section':
+        ensure  => present,
+        path    => "#{tmpdir}/ini_setting.ini",
+        section => 'one',
+        setting => 'two',
+        value   => 'three',
+      }
+      ini_setting { 'ensure => present for global':
+        ensure  => present,
+        path    => "#{tmpdir}/ini_setting.ini",
+        section => '',
+        setting => 'four',
+        value   => 'five',
+      }
+      EOS
+
+      it 'applies the manifest twice' do
+        apply_manifest(pp, :catch_failures => true)
+        apply_manifest(pp, :catch_changes => true)
+      end
+
+      it_behaves_like 'has_content', "#{tmpdir}/ini_setting.ini", pp, /four = five\n\n\[one\]\ntwo = three/
+    end
+
+    context '=> absent for key/value' do
+      before :all do
+        if fact('osfamily') == 'Darwin'
+          shell("echo \"four = five[one]\ntwo = three\" > #{tmpdir}/ini_setting.ini")
+        else
+          shell("echo -e \"four = five\n[one]\ntwo = three\" > #{tmpdir}/ini_setting.ini")
+        end
+      end
+
+      pp = <<-EOS
+      ini_setting { 'ensure => absent for key/value':
+        ensure  => absent,
+        path    => "#{tmpdir}/ini_setting.ini",
+        section => 'one',
+        setting => 'two',
+        value   => 'three',
+      }
+      EOS
+
+      it 'applies the manifest twice' do
+        apply_manifest(pp, :catch_failures => true)
+        apply_manifest(pp, :catch_changes => true)
+      end
+
+      describe file("#{tmpdir}/ini_setting.ini") do
+        it { should be_file }
+        its(:content) {
+          should match /four = five/
+          should match /\[one\]/
+          should_not match /two = three/
+        }
+      end
+    end
+
+    context '=> absent for global' do
+      before :all do
+        if fact('osfamily') == 'Darwin'
+          shell("echo \"four = five\n[one]\ntwo = three\" > #{tmpdir}/ini_setting.ini")
+        else
+          shell("echo -e \"four = five\n[one]\ntwo = three\" > #{tmpdir}/ini_setting.ini")
+        end
+      end
+      after :all do
+        shell("cat #{tmpdir}/ini_setting.ini", :acceptable_exit_codes => [0, 1, 2])
+        shell("rm #{tmpdir}/ini_setting.ini", :acceptable_exit_codes => [0, 1, 2])
+      end
+
+      pp = <<-EOS
+      ini_setting { 'ensure => absent for global':
+        ensure  => absent,
+        path    => "#{tmpdir}/ini_setting.ini",
+        section => '',
+        setting => 'four',
+        value   => 'five',
+      }
+      EOS
+
+      it 'applies the manifest twice' do
+        apply_manifest(pp, :catch_failures => true)
+        apply_manifest(pp, :catch_changes => true)
+      end
+
+      describe file("#{tmpdir}/ini_setting.ini") do
+        it { should be_file }
+        its(:content) {
+          should_not match /four = five/
+          should match /\[one\]/
+          should match /two = three/
+        }
+      end
+    end
+  end
+
+  describe 'section, setting, value parameters' do
+    {
+        "section => 'test', setting => 'foo', value => 'bar',"         => /\[test\]\nfoo = bar/,
+        "section => 'more', setting => 'baz', value => 'quux',"        => /\[more\]\nbaz = quux/,
+        "section => '',     setting => 'top', value => 'level',"       => /top = level/,
+        "section => 'z',    setting => 'sp aces', value => 'foo bar'," => /\[z\]\nsp aces = foo bar/,
+    }.each do |parameter_list, content|
+      context parameter_list do
+        pp = <<-EOS
+        ini_setting { "#{parameter_list}":
+          ensure  => present,
+          path    => "#{tmpdir}/ini_setting.ini",
+          #{parameter_list}
+        }
+        EOS
+
+        it_behaves_like 'has_content', "#{tmpdir}/ini_setting.ini", pp, content
+      end
+    end
+
+    {
+        "section => 'test',"                   => /setting is a required.+value is a required/,
+        "setting => 'foo',  value   => 'bar'," => /section is a required/,
+        "section => 'test', setting => 'foo'," => /value is a required/,
+        "section => 'test', value   => 'bar'," => /setting is a required/,
+        "value   => 'bar',"                    => /section is a required.+setting is a required/,
+        "setting => 'foo',"                    => /section is a required.+value is a required/,
+    }.each do |parameter_list, error|
+      context parameter_list, :pending => 'no error checking yet' do
+        pp = <<-EOS
+        ini_setting { "#{parameter_list}":
+          ensure  => present,
+          path    => "#{tmpdir}/ini_setting.ini",
+          #{parameter_list}
+        }
+        EOS
+
+        it_behaves_like 'has_error', "#{tmpdir}/ini_setting.ini", pp, error
+      end
+    end
+  end
+
+  describe 'path parameter' do
+    [
+        "#{tmpdir}/one.ini",
+        "#{tmpdir}/two.ini",
+        "#{tmpdir}/three.ini",
+    ].each do |path|
+      context "path => #{path}" do
+        pp = <<-EOS
+        ini_setting { 'path => #{path}':
+          ensure  => present,
+          section => 'one',
+          setting => 'two',
+          value   => 'three',
+          path    => '#{path}',
+        }
+        EOS
+
+        it_behaves_like 'has_content', path, pp, /\[one\]\ntwo = three/
+      end
+    end
+
+    context "path => foo" do
+      pp = <<-EOS
+        ini_setting { 'path => foo':
+          ensure     => present,
+          section    => 'one',
+          setting    => 'two',
+          value      => 'three',
+          path       => 'foo',
+        }
+      EOS
+
+      it_behaves_like 'has_error', 'foo', pp, /must be fully qualified/
+    end
+  end
+
+  describe 'key_val_separator parameter' do
+    {
+        ""                             => /two = three/,
+        "key_val_separator => '=',"    => /two=three/,
+        "key_val_separator => ' =  '," => /two =  three/,
+    }.each do |parameter, content|
+      context "with \"#{parameter}\" makes \"#{content}\"" do
+        pp = <<-EOS
+        ini_setting { "with #{parameter} makes #{content}":
+          ensure  => present,
+          section => 'one',
+          setting => 'two',
+          value   => 'three',
+          path    => "#{tmpdir}/key_val_separator.ini",
+          #{parameter}
+        }
+        EOS
+
+        it_behaves_like 'has_content', "#{tmpdir}/key_val_separator.ini", pp, content
+      end
+    end
+  end
+end
diff --git a/3rdparty/modules/inifile/spec/acceptance/ini_subsetting_spec.rb b/3rdparty/modules/inifile/spec/acceptance/ini_subsetting_spec.rb
new file mode 100644 (file)
index 0000000..d099a3b
--- /dev/null
@@ -0,0 +1,200 @@
+require 'spec_helper_acceptance'
+
+tmpdir = default.tmpdir('tmp')
+
+describe 'ini_subsetting resource' do
+  after :all do
+    shell("rm #{tmpdir}/*.ini", :acceptable_exit_codes => [0, 1, 2])
+  end
+
+  shared_examples 'has_content' do |path, pp, content|
+    before :all do
+      shell("rm #{path}", :acceptable_exit_codes => [0, 1, 2])
+    end
+    after :all do
+      shell("cat #{path}", :acceptable_exit_codes => [0, 1, 2])
+      shell("rm #{path}", :acceptable_exit_codes => [0, 1, 2])
+    end
+
+    it 'applies the manifest twice' do
+      apply_manifest(pp, :catch_failures => true)
+      apply_manifest(pp, :catch_changes => true)
+    end
+
+    describe file(path) do
+      it { should be_file }
+      its(:content) {
+        should match content
+      }
+    end
+  end
+
+  shared_examples 'has_error' do |path, pp, error|
+    before :all do
+      shell("rm #{path}", :acceptable_exit_codes => [0, 1, 2])
+    end
+    after :all do
+      shell("cat #{path}", :acceptable_exit_codes => [0, 1, 2])
+      shell("rm #{path}", :acceptable_exit_codes => [0, 1, 2])
+    end
+
+    it 'applies the manifest and gets a failure message' do
+      expect(apply_manifest(pp, :expect_failures => true).stderr).to match(error)
+    end
+
+    describe file(path) do
+      it { should_not be_file }
+    end
+  end
+
+  describe 'ensure, section, setting, subsetting, & value parameters' do
+    context '=> present with subsections' do
+      pp = <<-EOS
+      ini_subsetting { 'ensure => present for alpha':
+        ensure     => present,
+        path       => "#{tmpdir}/ini_subsetting.ini",
+        section    => 'one',
+        setting    => 'key',
+        subsetting => 'alpha',
+        value      => 'bet',
+      }
+      ini_subsetting { 'ensure => present for beta':
+        ensure     => present,
+        path       => "#{tmpdir}/ini_subsetting.ini",
+        section    => 'one',
+        setting    => 'key',
+        subsetting => 'beta',
+        value      => 'trons',
+        require    => Ini_subsetting['ensure => present for alpha'],
+      }
+      EOS
+
+      it 'applies the manifest twice' do
+        apply_manifest(pp, :catch_failures => true)
+        apply_manifest(pp, :catch_changes => true)
+      end
+
+      describe file("#{tmpdir}/ini_subsetting.ini") do
+        it { should be_file }
+        its(:content) {
+          should match /\[one\]\nkey = alphabet betatrons/
+        }
+      end
+    end
+
+    context 'ensure => absent' do
+      before :all do
+        if fact('osfamily') == 'Darwin'
+          shell("echo \"[one]\nkey = alphabet betatrons\" > #{tmpdir}/ini_subsetting.ini")
+        else
+          shell("echo -e \"[one]\nkey = alphabet betatrons\" > #{tmpdir}/ini_subsetting.ini")
+        end
+      end
+
+      pp = <<-EOS
+      ini_subsetting { 'ensure => absent for subsetting':
+        ensure     => absent,
+        path       => "#{tmpdir}/ini_subsetting.ini",
+        section    => 'one',
+        setting    => 'key',
+        subsetting => 'alpha',
+      }
+      EOS
+
+      it 'applies the manifest twice' do
+        apply_manifest(pp, :catch_failures => true)
+        apply_manifest(pp, :catch_changes => true)
+      end
+
+      describe file("#{tmpdir}/ini_subsetting.ini") do
+        it { should be_file }
+        its(:content) {
+          should match /\[one\]/
+          should match /key = betatrons/
+          should_not match /alphabet/
+        }
+      end
+    end
+  end
+
+  describe 'subsetting_separator' do
+    {
+        ""                                => /two = twinethree foobar/,
+        "subsetting_separator => ',',"    => /two = twinethree,foobar/,
+        "subsetting_separator => '   ',"  => /two = twinethree   foobar/,
+        "subsetting_separator => ' == '," => /two = twinethree == foobar/,
+        "subsetting_separator => '=',"    => /two = twinethree=foobar/,
+    }.each do |parameter, content|
+      context "with \"#{parameter}\" makes \"#{content}\"" do
+        pp = <<-EOS
+        ini_subsetting { "with #{parameter} makes #{content}":
+          ensure     => present,
+          section    => 'one',
+          setting    => 'two',
+          subsetting => 'twine',
+          value      => 'three',
+          path       => "#{tmpdir}/subsetting_separator.ini",
+          before     => Ini_subsetting['foobar'],
+          #{parameter}
+        }
+        ini_subsetting { "foobar":
+          ensure     => present,
+          section    => 'one',
+          setting    => 'two',
+          subsetting => 'foo',
+          value      => 'bar',
+          path       => "#{tmpdir}/subsetting_separator.ini",
+          #{parameter}
+        }
+        EOS
+
+        it_behaves_like 'has_content', "#{tmpdir}/subsetting_separator.ini", pp, content
+      end
+    end
+  end
+
+  describe 'quote_char' do
+    {
+        ['-Xmx']         => /args=""/,
+        ['-Xmx', '256m'] => /args=-Xmx256m/,
+        ['-Xmx', '512m'] => /args="-Xmx512m"/,
+        ['-Xms', '256m'] => /args="-Xmx256m -Xms256m"/,
+    }.each do |parameter, content|
+      context %Q{with '#{parameter.first}' #{parameter.length > 1 ? '=> \'' << parameter[1] << '\'' : 'absent'} makes '#{content}'} do
+        path = File.join(tmpdir, 'ini_subsetting.ini')
+
+        before :all do
+          shell(%Q{echo '[java]\nargs=-Xmx256m' > #{path}})
+        end
+        after :all do
+          shell("cat #{path}", :acceptable_exit_codes => [0, 1, 2])
+          shell("rm #{path}", :acceptable_exit_codes => [0, 1, 2])
+        end
+
+        pp = <<-EOS
+        ini_subsetting { '#{parameter.first}':
+          ensure     => #{parameter.length > 1 ? 'present' : 'absent'},
+          path       => '#{path}',
+          section    => 'java',
+          setting    => 'args',
+          quote_char => '"',
+          subsetting => '#{parameter.first}',
+          value      => '#{parameter.length > 1 ? parameter[1] : ''}'
+        }
+        EOS
+
+        it 'applies the manifest twice' do
+          apply_manifest(pp, :catch_failures => true)
+          apply_manifest(pp, :catch_changes => true)
+        end
+
+        describe file("#{tmpdir}/ini_subsetting.ini") do
+          it { should be_file }
+          its(:content) {
+            should match content
+          }
+        end
+      end
+    end
+  end
+end
diff --git a/3rdparty/modules/inifile/spec/acceptance/nodesets/centos-510-x64.yml b/3rdparty/modules/inifile/spec/acceptance/nodesets/centos-510-x64.yml
new file mode 100644 (file)
index 0000000..12c9e78
--- /dev/null
@@ -0,0 +1,10 @@
+HOSTS:
+  centos-510-x64:
+    roles:
+      - master
+    platform: el-5-x86_64
+    box : centos-510-x64-virtualbox-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-510-x64-virtualbox-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  type: git
diff --git a/3rdparty/modules/inifile/spec/acceptance/nodesets/centos-59-x64.yml b/3rdparty/modules/inifile/spec/acceptance/nodesets/centos-59-x64.yml
new file mode 100644 (file)
index 0000000..2ad90b8
--- /dev/null
@@ -0,0 +1,10 @@
+HOSTS:
+  centos-59-x64:
+    roles:
+      - master
+    platform: el-5-x86_64
+    box : centos-59-x64-vbox4210-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-59-x64-vbox4210-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  type: git
diff --git a/3rdparty/modules/inifile/spec/acceptance/nodesets/centos-64-x64-pe.yml b/3rdparty/modules/inifile/spec/acceptance/nodesets/centos-64-x64-pe.yml
new file mode 100644 (file)
index 0000000..7d9242f
--- /dev/null
@@ -0,0 +1,12 @@
+HOSTS:
+  centos-64-x64:
+    roles:
+      - master
+      - database
+      - dashboard
+    platform: el-6-x86_64
+    box : centos-64-x64-vbox4210-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-64-x64-vbox4210-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  type: pe
diff --git a/3rdparty/modules/inifile/spec/acceptance/nodesets/centos-64-x64.yml b/3rdparty/modules/inifile/spec/acceptance/nodesets/centos-64-x64.yml
new file mode 100644 (file)
index 0000000..0639835
--- /dev/null
@@ -0,0 +1,10 @@
+HOSTS:
+  centos-64-x64:
+    roles:
+      - master
+    platform: el-6-x86_64
+    box : centos-64-x64-vbox4210-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-64-x64-vbox4210-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  type: git
diff --git a/3rdparty/modules/inifile/spec/acceptance/nodesets/centos-65-x64.yml b/3rdparty/modules/inifile/spec/acceptance/nodesets/centos-65-x64.yml
new file mode 100644 (file)
index 0000000..4e2cb80
--- /dev/null
@@ -0,0 +1,10 @@
+HOSTS:
+  centos-65-x64:
+    roles:
+      - master
+    platform: el-6-x86_64
+    box : centos-65-x64-vbox436-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-65-x64-virtualbox-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  type: foss
diff --git a/3rdparty/modules/inifile/spec/acceptance/nodesets/debian-607-x64.yml b/3rdparty/modules/inifile/spec/acceptance/nodesets/debian-607-x64.yml
new file mode 100644 (file)
index 0000000..4c8be42
--- /dev/null
@@ -0,0 +1,10 @@
+HOSTS:
+  debian-607-x64:
+    roles:
+      - master
+    platform: debian-6-amd64
+    box : debian-607-x64-vbox4210-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/debian-607-x64-vbox4210-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  type: git
diff --git a/3rdparty/modules/inifile/spec/acceptance/nodesets/debian-73-x64.yml b/3rdparty/modules/inifile/spec/acceptance/nodesets/debian-73-x64.yml
new file mode 100644 (file)
index 0000000..3e31a82
--- /dev/null
@@ -0,0 +1,10 @@
+HOSTS:
+  debian-73-x64:
+    roles:
+      - master
+    platform: debian-7-amd64
+    box : debian-73-x64-virtualbox-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/debian-73-x64-virtualbox-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  type: git
diff --git a/3rdparty/modules/inifile/spec/acceptance/nodesets/default.yml b/3rdparty/modules/inifile/spec/acceptance/nodesets/default.yml
new file mode 100644 (file)
index 0000000..0639835
--- /dev/null
@@ -0,0 +1,10 @@
+HOSTS:
+  centos-64-x64:
+    roles:
+      - master
+    platform: el-6-x86_64
+    box : centos-64-x64-vbox4210-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-64-x64-vbox4210-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  type: git
diff --git a/3rdparty/modules/inifile/spec/acceptance/nodesets/fedora-18-x64.yml b/3rdparty/modules/inifile/spec/acceptance/nodesets/fedora-18-x64.yml
new file mode 100644 (file)
index 0000000..624b537
--- /dev/null
@@ -0,0 +1,10 @@
+HOSTS:
+  fedora-18-x64:
+    roles:
+      - master
+    platform: fedora-18-x86_64
+    box : fedora-18-x64-vbox4210-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/fedora-18-x64-vbox4210-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  type: git
diff --git a/3rdparty/modules/inifile/spec/acceptance/nodesets/sles-11sp1-x64.yml b/3rdparty/modules/inifile/spec/acceptance/nodesets/sles-11sp1-x64.yml
new file mode 100644 (file)
index 0000000..554c37a
--- /dev/null
@@ -0,0 +1,10 @@
+HOSTS:
+  sles-11sp1-x64:
+    roles:
+      - master
+    platform: sles-11-x86_64
+    box : sles-11sp1-x64-vbox4210-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/sles-11sp1-x64-vbox4210-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  type: git
diff --git a/3rdparty/modules/inifile/spec/acceptance/nodesets/ubuntu-server-10044-x64.yml b/3rdparty/modules/inifile/spec/acceptance/nodesets/ubuntu-server-10044-x64.yml
new file mode 100644 (file)
index 0000000..5ca1514
--- /dev/null
@@ -0,0 +1,10 @@
+HOSTS:
+  ubuntu-server-10044-x64:
+    roles:
+      - master
+    platform: ubuntu-10.04-amd64
+    box : ubuntu-server-10044-x64-vbox4210-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/ubuntu-server-10044-x64-vbox4210-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  type: foss
diff --git a/3rdparty/modules/inifile/spec/acceptance/nodesets/ubuntu-server-12042-x64.yml b/3rdparty/modules/inifile/spec/acceptance/nodesets/ubuntu-server-12042-x64.yml
new file mode 100644 (file)
index 0000000..d065b30
--- /dev/null
@@ -0,0 +1,10 @@
+HOSTS:
+  ubuntu-server-12042-x64:
+    roles:
+      - master
+    platform: ubuntu-12.04-amd64
+    box : ubuntu-server-12042-x64-vbox4210-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/ubuntu-server-12042-x64-vbox4210-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  type: foss
diff --git a/3rdparty/modules/inifile/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml b/3rdparty/modules/inifile/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml
new file mode 100644 (file)
index 0000000..cba1cd0
--- /dev/null
@@ -0,0 +1,11 @@
+HOSTS:
+  ubuntu-server-1404-x64:
+    roles:
+      - master
+    platform: ubuntu-14.04-amd64
+    box : puppetlabs/ubuntu-14.04-64-nocm
+    box_url : https://vagrantcloud.com/puppetlabs/ubuntu-14.04-64-nocm
+    hypervisor : vagrant
+CONFIG:
+  log_level   : debug
+  type: git
diff --git a/3rdparty/modules/inifile/spec/acceptance/nodesets/windows-2003-i386.yml b/3rdparty/modules/inifile/spec/acceptance/nodesets/windows-2003-i386.yml
new file mode 100644 (file)
index 0000000..eb571ee
--- /dev/null
@@ -0,0 +1,24 @@
+HOSTS:
+  ubuntu1204:
+    roles:
+      - master
+      - database
+      - dashboard
+    platform: ubuntu-12.04-amd64
+    template: ubuntu-1204-x86_64
+    hypervisor: vcloud
+  win2003_i386:
+    roles:
+      - agent
+      - default
+    platform: windows-2003-i386
+    template: win-2003-i386
+    hypervisor: vcloud
+CONFIG:
+  nfs_server: none
+  consoleport: 443
+  datastore: instance0
+  folder: Delivery/Quality Assurance/Enterprise/Dynamic
+  resourcepool: delivery/Quality Assurance/Enterprise/Dynamic
+  pooling_api: http://vcloud.delivery.puppetlabs.net/
+  pe_dir: http://neptune.puppetlabs.lan/3.2/ci-ready/
diff --git a/3rdparty/modules/inifile/spec/acceptance/nodesets/windows-2003r2-x86_64.yml b/3rdparty/modules/inifile/spec/acceptance/nodesets/windows-2003r2-x86_64.yml
new file mode 100644 (file)
index 0000000..e8659a5
--- /dev/null
@@ -0,0 +1,24 @@
+HOSTS:
+  ubuntu1204:
+    roles:
+      - master
+      - database
+      - dashboard
+    platform: ubuntu-12.04-amd64
+    template: ubuntu-1204-x86_64
+    hypervisor: vcloud
+  win2003r2_x86_64:
+    roles:
+      - agent
+      - default
+    platform: windows-2003r2-x86_64
+    template: win-2003r2-x86_64
+    hypervisor: vcloud
+CONFIG:
+  nfs_server: none
+  consoleport: 443
+  datastore: instance0
+  folder: Delivery/Quality Assurance/Enterprise/Dynamic
+  resourcepool: delivery/Quality Assurance/Enterprise/Dynamic
+  pooling_api: http://vcloud.delivery.puppetlabs.net/
+  pe_dir: http://neptune.puppetlabs.lan/3.3/ci-ready/
diff --git a/3rdparty/modules/inifile/spec/acceptance/nodesets/windows-2008-x86_64.yml b/3rdparty/modules/inifile/spec/acceptance/nodesets/windows-2008-x86_64.yml
new file mode 100644 (file)
index 0000000..a5ebc4d
--- /dev/null
@@ -0,0 +1,24 @@
+HOSTS:
+  ubuntu1204:
+    roles:
+      - master
+      - database
+      - dashboard
+    platform: ubuntu-12.04-amd64
+    template: ubuntu-1204-x86_64
+    hypervisor: vcloud
+  win2008_x86_64:
+    roles:
+      - agent
+      - default
+    platform: windows-2008-x86_64
+    template: win-2008-x86_64
+    hypervisor: vcloud
+CONFIG:
+  nfs_server: none
+  consoleport: 443
+  datastore: instance0
+  folder: Delivery/Quality Assurance/Enterprise/Dynamic
+  resourcepool: delivery/Quality Assurance/Enterprise/Dynamic
+  pooling_api: http://vcloud.delivery.puppetlabs.net/
+  pe_dir: http://neptune.puppetlabs.lan/3.3/ci-ready/
diff --git a/3rdparty/modules/inifile/spec/acceptance/nodesets/windows-2008r2-x86_64.yml b/3rdparty/modules/inifile/spec/acceptance/nodesets/windows-2008r2-x86_64.yml
new file mode 100644 (file)
index 0000000..d2ddba3
--- /dev/null
@@ -0,0 +1,24 @@
+HOSTS:
+  ubuntu1204:
+    roles:
+      - master
+      - database
+      - dashboard
+    platform: ubuntu-12.04-amd64
+    template: ubuntu-1204-x86_64
+    hypervisor: vcloud
+  win2008r2:
+    roles:
+      - agent
+      - default
+    platform: windows-2008r2-x86_64
+    template: win-2008r2-x86_64
+    hypervisor: vcloud
+CONFIG:
+  nfs_server: none
+  consoleport: 443
+  datastore: instance0
+  folder: Delivery/Quality Assurance/Enterprise/Dynamic
+  resourcepool: delivery/Quality Assurance/Enterprise/Dynamic
+  pooling_api: http://vcloud.delivery.puppetlabs.net/
+  pe_dir: http://neptune.puppetlabs.lan/3.3/ci-ready/
diff --git a/3rdparty/modules/inifile/spec/acceptance/nodesets/windows-2012-x86_64.yml b/3rdparty/modules/inifile/spec/acceptance/nodesets/windows-2012-x86_64.yml
new file mode 100644 (file)
index 0000000..deea376
--- /dev/null
@@ -0,0 +1,24 @@
+HOSTS:
+  ubuntu1204:
+    roles:
+      - master
+      - database
+      - dashboard
+    platform: ubuntu-12.04-amd64
+    template: ubuntu-1204-x86_64
+    hypervisor: vcloud
+  win2012:
+    roles:
+      - agent
+      - default
+    platform: windows-2012-x86_64
+    template: win-2012-x86_64
+    hypervisor: vcloud
+CONFIG:
+  nfs_server: none
+  consoleport: 443
+  datastore: instance0
+  folder: Delivery/Quality Assurance/Enterprise/Dynamic
+  resourcepool: delivery/Quality Assurance/Enterprise/Dynamic
+  pooling_api: http://vcloud.delivery.puppetlabs.net/
+  pe_dir: http://neptune.puppetlabs.lan/3.3/ci-ready/
diff --git a/3rdparty/modules/inifile/spec/acceptance/nodesets/windows-2012r2-x86_64.yml b/3rdparty/modules/inifile/spec/acceptance/nodesets/windows-2012r2-x86_64.yml
new file mode 100644 (file)
index 0000000..8f9149a
--- /dev/null
@@ -0,0 +1,24 @@
+HOSTS:
+  ubuntu1204:
+    roles:
+      - master
+      - database
+      - dashboard
+    platform: ubuntu-12.04-amd64
+    template: ubuntu-1204-x86_64
+    hypervisor: vcloud
+  win2012r2:
+    roles:
+      - agent
+      - default
+    platform: windows-2012r2-x86_64
+    template: win-2012r2-x86_64
+    hypervisor: vcloud
+CONFIG:
+  nfs_server: none
+  consoleport: 443
+  datastore: instance0
+  folder: Delivery/Quality Assurance/Enterprise/Dynamic
+  resourcepool: delivery/Quality Assurance/Enterprise/Dynamic
+  pooling_api: http://vcloud.delivery.puppetlabs.net/
+  pe_dir: http://neptune.puppetlabs.lan/3.3/ci-ready/
diff --git a/3rdparty/modules/inifile/spec/classes/create_ini_settings_test_spec.rb b/3rdparty/modules/inifile/spec/classes/create_ini_settings_test_spec.rb
new file mode 100644 (file)
index 0000000..4e6683a
--- /dev/null
@@ -0,0 +1,25 @@
+require 'spec_helper'
+# end-to-end test of the create_init_settings function
+describe 'create_ini_settings_test' do
+  it { should have_ini_setting_resource_count(3) }
+  it { should contain_ini_setting('[section1] setting1').with(
+    :ensure  => 'present',
+    :section => 'section1',
+    :setting => 'setting1',
+    :value   => 'val1',
+    :path    => '/tmp/foo.ini'
+  )}
+  it { should contain_ini_setting('[section2] setting2').with(
+    :ensure  => 'present',
+    :section => 'section2',
+    :setting => 'setting2',
+    :value   => 'val2',
+    :path    => '/tmp/foo.ini'
+  )}
+  it { should contain_ini_setting('[section2] setting3').with(
+    :ensure  => 'absent',
+    :section => 'section2',
+    :setting => 'setting3',
+    :path    => '/tmp/foo.ini'
+  )}
+end
diff --git a/3rdparty/modules/inifile/spec/classes/inherit_test1_spec.rb b/3rdparty/modules/inifile/spec/classes/inherit_test1_spec.rb
new file mode 100644 (file)
index 0000000..51fc0c2
--- /dev/null
@@ -0,0 +1,10 @@
+require 'spec_helper'
+# We can't really test much here, apart from the type roundtrips though the
+# parser OK.
+describe 'inherit_test1' do
+  it do
+    should contain_inherit_ini_setting('valid_type').with({
+      'value' => 'true'
+    })
+  end
+end
diff --git a/3rdparty/modules/inifile/spec/functions/create_ini_settings_spec.rb b/3rdparty/modules/inifile/spec/functions/create_ini_settings_spec.rb
new file mode 100644 (file)
index 0000000..e40fb09
--- /dev/null
@@ -0,0 +1,23 @@
+#! /usr/bin/env ruby
+
+require 'spec_helper'
+require 'rspec-puppet'
+
+describe 'create_ini_settings' do
+  before :each do
+    Puppet::Parser::Functions.autoloader.loadall
+    Puppet::Parser::Functions.function(:create_resources)
+  end
+
+  describe 'argument handling' do
+    it { should run.with_params.and_raise_error(Puppet::ParseError, /0 for 1 or 2/) }
+    it { should run.with_params(1,2,3).and_raise_error(Puppet::ParseError, /3 for 1 or 2/) }
+    it { should run.with_params('foo').and_raise_error(Puppet::ParseError, /Requires all arguments/) }
+    it { should run.with_params({},'foo').and_raise_error(Puppet::ParseError, /Requires all arguments/) }
+
+    it { should run.with_params({}) }
+    it { should run.with_params({},{}) }
+
+    it { should run.with_params({ 1 => 2 }).and_raise_error(Puppet::ParseError, /Section 1 must contain a Hash/) }
+  end
+end
diff --git a/3rdparty/modules/inifile/spec/spec.opts b/3rdparty/modules/inifile/spec/spec.opts
new file mode 100644 (file)
index 0000000..91cd642
--- /dev/null
@@ -0,0 +1,6 @@
+--format
+s
+--colour
+--loadby
+mtime
+--backtrace
diff --git a/3rdparty/modules/inifile/spec/spec_helper.rb b/3rdparty/modules/inifile/spec/spec_helper.rb
new file mode 100644 (file)
index 0000000..7607c33
--- /dev/null
@@ -0,0 +1,5 @@
+require 'puppetlabs_spec_helper/module_spec_helper'
+
+RSpec.configure do |config|
+  config.mock_with :rspec
+end
diff --git a/3rdparty/modules/inifile/spec/spec_helper_acceptance.rb b/3rdparty/modules/inifile/spec/spec_helper_acceptance.rb
new file mode 100644 (file)
index 0000000..80a6b62
--- /dev/null
@@ -0,0 +1,39 @@
+require 'beaker-rspec/spec_helper'
+require 'beaker-rspec/helpers/serverspec'
+
+unless ENV['RS_PROVISION'] == 'no'
+  # This will install the latest available package on el and deb based
+  # systems fail on windows and osx, and install via gem on other *nixes
+  foss_opts = {:default_action => 'gem_install'}
+
+  if default.is_pe?; then
+    install_pe;
+  else
+    install_puppet(foss_opts);
+  end
+
+  hosts.each do |host|
+    if host['platform'] =~ /debian/
+      on host, 'echo \'export PATH=/var/lib/gems/1.8/bin/:${PATH}\' >> ~/.bashrc'
+      on host, "mkdir -p #{host['distmoduledir']}"
+    end
+  end
+end
+
+RSpec.configure do |c|
+  # Project root
+  proj_root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
+
+  # Readable test descriptions
+  c.formatter = :documentation
+
+  # Configure all nodes in nodeset
+  c.before :suite do
+    # Install module and dependencies
+    hosts.each do |host|
+      copy_root_module_to(host, :source => proj_root, :module_name => 'inifile')
+    end
+  end
+
+  c.treat_symbols_as_metadata_keys_with_true_values = true
+end
diff --git a/3rdparty/modules/inifile/spec/unit/puppet/provider/ini_setting/inheritance_spec.rb b/3rdparty/modules/inifile/spec/unit/puppet/provider/ini_setting/inheritance_spec.rb
new file mode 100644 (file)
index 0000000..4dd6c3f
--- /dev/null
@@ -0,0 +1,67 @@
+require 'spec_helper'
+
+# This is a reduced version of ruby_spec.rb just to ensure we can subclass as
+# documented
+$: << 'spec/fixtures/modules/inherit_ini_setting/lib'
+provider_class = Puppet::Type.type(:inherit_ini_setting).provider(:ini_setting)
+describe provider_class do
+  include PuppetlabsSpec::Files
+
+  let(:tmpfile) { tmpfilename('inherit_ini_setting_test') }
+
+  def validate_file(expected_content,tmpfile = tmpfile)
+    File.read(tmpfile).should == expected_content
+  end
+
+
+  before :each do
+    File.open(tmpfile, 'w') do |fh|
+      fh.write(orig_content)
+    end
+  end
+
+  context 'when calling instances' do
+    let(:orig_content) { '' }
+
+    it 'should parse nothing when the file is empty' do
+      provider_class.stubs(:file_path).returns(tmpfile)
+      provider_class.instances.should == []
+    end
+
+    context 'when the file has contents' do
+      let(:orig_content) {
+        <<-EOS
+# A comment
+red = blue
+green = purple
+        EOS
+      }
+
+      it 'should parse the results' do
+        provider_class.stubs(:file_path).returns(tmpfile)
+        instances = provider_class.instances
+        instances.size.should == 2
+        # inherited version of namevar flattens the names
+        names = instances.map do |instance|
+          instance.instance_variable_get(:@property_hash)[:name]
+        end
+        names.sort.should == [ 'green', 'red' ]
+      end
+    end
+  end
+
+  context 'when ensuring that a setting is present' do
+    let(:orig_content) { '' }
+
+    it 'should add a value to the file' do
+      provider_class.stubs(:file_path).returns(tmpfile)
+      resource = Puppet::Type::Inherit_ini_setting.new({
+        :setting => 'set_this',
+        :value   => 'to_that',
+      })
+      provider = described_class.new(resource)
+      provider.create
+      validate_file("set_this=to_that\n")
+    end
+  end
+end
diff --git a/3rdparty/modules/inifile/spec/unit/puppet/provider/ini_setting/ruby_spec.rb b/3rdparty/modules/inifile/spec/unit/puppet/provider/ini_setting/ruby_spec.rb
new file mode 100644 (file)
index 0000000..c3f5ccf
--- /dev/null
@@ -0,0 +1,1362 @@
+require 'spec_helper'
+require 'puppet'
+
+provider_class = Puppet::Type.type(:ini_setting).provider(:ruby)
+describe provider_class do
+  include PuppetlabsSpec::Files
+
+  let(:tmpfile) { tmpfilename("ini_setting_test") }
+  let(:emptyfile) { tmpfilename("ini_setting_test_empty") }
+
+  let(:common_params) { {
+      :title    => 'ini_setting_ensure_present_test',
+      :path     => tmpfile,
+      :section  => 'section2',
+  } }
+
+  def validate_file(expected_content,tmpfile = tmpfile)
+    File.read(tmpfile).should == expected_content
+  end
+
+
+  before :each do
+    File.open(tmpfile, 'w') do |fh|
+      fh.write(orig_content)
+    end
+    File.open(emptyfile, 'w') do |fh|
+      fh.write("")
+    end
+  end
+
+  context 'when calling instances' do
+
+    let :orig_content do
+      ''
+    end
+
+    it 'should fail when file path is not set' do
+      expect {
+        provider_class.instances
+      }.to raise_error(Puppet::Error, 'Ini_settings only support collecting instances when a file path is hard coded')
+    end
+
+    context 'when file path is set by a child class' do
+      it 'should return [] when file is empty' do
+        child_one = Class.new(provider_class) do
+          def self.file_path
+            emptyfile
+          end
+        end
+        child_one.stubs(:file_path).returns(emptyfile)
+        child_one.instances.should == []
+      end
+      it 'should override the provider instances file_path' do
+        child_two = Class.new(provider_class) do
+          def self.file_path
+            '/some/file/path'
+          end
+        end
+        resource = Puppet::Type::Ini_setting.new(common_params)
+        provider = child_two.new(resource)
+        provider.file_path.should == '/some/file/path'
+      end
+      context 'when file has contecnts' do
+        let(:orig_content) {
+          <<-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
+          EOS
+        }
+
+        it 'should be able to parse the results' do
+          child_three = Class.new(provider_class) do
+            def self.file_path
+              '/some/file/path'
+            end
+          end
+          child_three.stubs(:file_path).returns(tmpfile)
+          child_three.instances.size == 7
+          expected_array = [
+            {:name => 'section1/foo', :value => 'foovalue' },
+            {:name => 'section1/bar', :value => 'barvalue' },
+            {:name => 'section1/master', :value => 'true' },
+            {:name => 'section2/foo', :value => 'foovalue2' },
+            {:name => 'section2/baz', :value => 'bazvalue' },
+            {:name => 'section2/url', :value => 'http://192.168.1.1:8080' },
+            {:name => 'section:sub/subby', :value => 'bar' }
+          ]
+          real_array = []
+          ensure_array = []
+          child_three.instances.each do |x|
+            prop_hash    = x.instance_variable_get(:@property_hash)
+            ensure_value = prop_hash.delete(:ensure)
+            ensure_array.push(ensure_value)
+            real_array.push(prop_hash)
+          end
+          ensure_array.uniq.should == [:present]
+          ((real_array - expected_array) && (expected_array - real_array)).should == []
+
+        end
+
+      end
+
+    end
+
+  end
+
+  context "when ensuring that a setting is present" do
+    let(:orig_content) {
+      <<-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
+      EOS
+    }
+
+    it "should add a missing setting to the correct section" do
+      resource = Puppet::Type::Ini_setting.new(common_params.merge(
+          :setting => 'yahoo', :value => 'yippee'))
+      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
+yahoo = yippee
+[section:sub]
+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
+
+    it "should add a missing setting to the correct section with colon" do
+      resource = Puppet::Type::Ini_setting.new(common_params.merge(
+          :section => 'section:sub', :setting => 'yahoo', :value => 'yippee'))
+      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
+
+    it "should modify an existing setting with a different value" do
+      resource = Puppet::Type::Ini_setting.new(common_params.merge(
+           :setting => 'baz', :value => 'bazvalue2'))
+      provider = described_class.new(resource)
+      provider.exists?.should be true
+      provider.value=('bazvalue2')
+      validate_file(<<-EOS
+# This is a comment
+[section1]
+; This is also a comment
+foo=foovalue
+
+bar = barvalue
+master = true
+[section2]
+
+foo= foovalue2
+baz=bazvalue2
+url = http://192.168.1.1:8080
+[section:sub]
+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
+
+    it "should modify an existing setting with a different value - with colon in section" do
+      resource = Puppet::Type::Ini_setting.new(common_params.merge(
+           :section => 'section:sub', :setting => 'subby', :value => 'foo'))
+      provider = described_class.new(resource)
+      provider.exists?.should be true
+      provider.value.should == 'bar'
+      provider.value=('foo')
+      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=foo
+    #another comment
+ ; yet another comment
+
+-nonstandard-
+  shoes = purple
+      EOS
+      )
+    end
+
+    it "should be able to handle settings with non alphanumbering settings " do
+      resource = Puppet::Type::Ini_setting.new(common_params.merge(
+           :setting => 'url', :value => 'http://192.168.0.1:8080'))
+      provider = described_class.new(resource)
+      provider.exists?.should be true
+      provider.value.should == 'http://192.168.1.1:8080'
+      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.0.1:8080
+[section:sub]
+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
+
+    it "should recognize an existing setting with the specified value" do
+      resource = Puppet::Type::Ini_setting.new(common_params.merge(
+           :setting => 'baz', :value => 'bazvalue'))
+      provider = described_class.new(resource)
+      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'))
+      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 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'))
+      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 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))
+      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 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))
+      provider = described_class.new(resource)
+      provider.exists?.should be false
+      provider.create
+      validate_file("
+[section:subsection]
+setting1 = hellowworld
+", 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))
+      provider = described_class.new(resource)
+      provider.exists?.should be true
+      provider.value.should == 'true'
+    end
+
+  end
+
+  context "when dealing with a global section" do
+    let(:orig_content) {
+      <<-EOS
+# This is a comment
+foo=blah
+[section2]
+foo = http://192.168.1.1:8080
+ ; yet another comment
+      EOS
+    }
+
+
+    it "should add a missing setting if it doesn't exist" do
+      resource = Puppet::Type::Ini_setting.new(common_params.merge(
+          :section => '', :setting => 'bar', :value => 'yippee'))
+      provider = described_class.new(resource)
+      provider.exists?.should be false
+      provider.create
+      validate_file(<<-EOS
+# This is a comment
+foo=blah
+bar = yippee
+[section2]
+foo = http://192.168.1.1:8080
+ ; yet another comment
+      EOS
+      )
+    end
+
+    it "should modify an existing setting with a different value" do
+      resource = Puppet::Type::Ini_setting.new(common_params.merge(
+           :section => '', :setting => 'foo', :value => 'yippee'))
+      provider = described_class.new(resource)
+      provider.exists?.should be true
+      provider.value.should == 'blah'
+      provider.value=('yippee')
+      validate_file(<<-EOS
+# This is a comment
+foo=yippee
+[section2]
+foo = http://192.168.1.1:8080
+ ; yet another comment
+      EOS
+      )
+    end
+
+    it "should recognize an existing setting with the specified value" do
+      resource = Puppet::Type::Ini_setting.new(common_params.merge(
+           :section => '', :setting => 'foo', :value => 'blah'))
+      provider = described_class.new(resource)
+      provider.exists?.should be true
+    end
+  end
+
+  context "when the first line of the file is a section" do
+    let(:orig_content) {
+      <<-EOS
+[section2]
+foo = http://192.168.1.1:8080
+      EOS
+    }
+
+    it "should be able to add a global setting" do
+      resource = Puppet::Type::Ini_setting.new(common_params.merge(
+           :section => '', :setting => 'foo', :value => 'yippee'))
+      provider = described_class.new(resource)
+      provider.exists?.should be false
+      provider.create
+      validate_file(<<-EOS
+foo = yippee
+
+[section2]
+foo = http://192.168.1.1:8080
+      EOS
+      )
+    end
+
+    it "should modify an existing setting" do
+      resource = Puppet::Type::Ini_setting.new(common_params.merge(
+          :section => 'section2', :setting => 'foo', :value => 'yippee'))
+      provider = described_class.new(resource)
+      provider.exists?.should be true
+      provider.value.should == 'http://192.168.1.1:8080'
+      provider.value=('yippee')
+      validate_file(<<-EOS
+[section2]
+foo = yippee
+      EOS
+      )
+    end
+
+    it "should add a new setting" do
+      resource = Puppet::Type::Ini_setting.new(common_params.merge(
+          :section => 'section2', :setting => 'bar', :value => 'baz'))
+      provider = described_class.new(resource)
+      provider.exists?.should be false
+      provider.create
+      validate_file(<<-EOS
+[section2]
+foo = http://192.168.1.1:8080
+bar = baz
+      EOS
+      )
+    end
+  end
+
+  context "when overriding the separator" do
+    let(:orig_content) {
+      <<-EOS
+[section2]
+foo=bar
+      EOS
+    }
+
+    it "should modify an existing setting" do
+      resource = Puppet::Type::Ini_setting.new(common_params.merge(
+                                                   :section           => 'section2',
+                                                   :setting           => 'foo',
+                                                   :value             => 'yippee',
+                                                   :key_val_separator => '='))
+      provider = described_class.new(resource)
+      provider.exists?.should be true
+      provider.value.should == 'bar'
+      provider.value=('yippee')
+      validate_file(<<-EOS
+[section2]
+foo=yippee
+      EOS
+      )
+    end
+
+  end
+
+  context "when overriding the separator to something other than =" do
+    let(:orig_content) {
+      <<-EOS
+[section2]
+foo: bar
+      EOS
+    }
+
+    it "should modify an existing setting" do
+      resource = Puppet::Type::Ini_setting.new(common_params.merge(
+                                                   :section           => 'section2',
+                                                   :setting           => 'foo',
+                                                   :value             => 'yippee',
+                                                   :key_val_separator => ': '))
+      provider = described_class.new(resource)
+      provider.exists?.should be true
+      provider.value.should == 'bar'
+      provider.value=('yippee')
+      validate_file(<<-EOS
+[section2]
+foo: yippee
+      EOS
+      )
+    end
+
+    it "should add a new setting" do
+      resource = Puppet::Type::Ini_setting.new(common_params.merge(
+                                                   :section           => 'section2',
+                                                   :setting           => 'bar',
+                                                   :value             => 'baz',
+                                                   :key_val_separator => ': '))
+      provider = described_class.new(resource)
+      provider.exists?.should be false
+      provider.create
+      validate_file(<<-EOS
+[section2]
+foo: bar
+bar: baz
+      EOS
+      )
+    end
+
+  end
+
+  context "when ensuring that a setting is absent" do
+    let(:orig_content) {
+      <<-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
+    }
+
+    it "should remove a setting that exists" do
+      resource = Puppet::Type::Ini_setting.new(common_params.merge(
+      :section => 'section1', :setting => 'foo', :ensure => 'absent'))
+      provider = described_class.new(resource)
+      provider.exists?.should be true
+      provider.destroy
+      validate_file(<<-EOS
+[section1]
+; This is also a comment
+
+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
+
+    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
+
+    it "should do nothing for a setting that does not exist" do
+      resource = Puppet::Type::Ini_setting.new(common_params.merge(
+                                                   :section => 'section:sub', :setting => 'foo', :ensure => 'absent'))
+      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
+
+    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) {
+      <<-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
+  fleezy = flam
+ ; yet another comment
+      EOS
+    }
+
+    it "should add a missing setting at the correct indentation when the header is aligned" do
+      resource = Puppet::Type::Ini_setting.new(common_params.merge(
+                    :section => 'section1', :setting => 'yahoo', :value => 'yippee'))
+      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
+     yahoo = yippee
+
+[section2]
+  foo= foovalue2
+  baz=bazvalue
+  url = http://192.168.1.1:8080
+[section:sub]
+ subby=bar
+    #another comment
+  fleezy = flam
+ ; yet another comment
+      EOS
+      )
+    end
+
+    it "should update an existing setting at the correct indentation when the header is aligned" do
+      resource = Puppet::Type::Ini_setting.new(
+          common_params.merge(:section => 'section1', :setting => 'bar', :value => 'barvalue2'))
+      provider = described_class.new(resource)
+      provider.exists?.should be true
+      provider.create
+      validate_file(<<-EOS
+# This is a comment
+     [section1]
+     ; This is also a comment
+     foo=foovalue
+
+     bar = barvalue2
+     master = true
+
+[section2]
+  foo= foovalue2
+  baz=bazvalue
+  url = http://192.168.1.1:8080
+[section:sub]
+ subby=bar
+    #another comment
+  fleezy = flam
+ ; yet another comment
+      EOS
+      )
+    end
+
+    it "should add a missing setting at the correct indentation when the header is not aligned" do
+      resource = Puppet::Type::Ini_setting.new(common_params.merge(
+                                                   :section => 'section2', :setting => 'yahoo', :value => 'yippee'))
+      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
+  yahoo = yippee
+[section:sub]
+ subby=bar
+    #another comment
+  fleezy = flam
+ ; yet another comment
+      EOS
+      )
+    end
+
+    it "should update an existing setting at the correct indentation when the header is not aligned" do
+      resource = Puppet::Type::Ini_setting.new(
+          common_params.merge(:section => 'section2', :setting => 'baz', :value => 'bazvalue2'))
+      provider = described_class.new(resource)
+      provider.exists?.should be true
+      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=bazvalue2
+  url = http://192.168.1.1:8080
+[section:sub]
+ subby=bar
+    #another comment
+  fleezy = flam
+ ; yet another comment
+      EOS
+      )
+    end
+
+    it "should add a missing setting at the min indentation when the section is not aligned" do
+      resource = Puppet::Type::Ini_setting.new(
+          common_params.merge(:section => 'section:sub', :setting => 'yahoo', :value => 'yippee'))
+      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
+  fleezy = flam
+ ; yet another comment
+ yahoo = yippee
+      EOS
+      )
+    end
+
+    it "should update an existing setting at the previous indentation when the section is not aligned" do
+      resource = Puppet::Type::Ini_setting.new(
+          common_params.merge(:section => 'section:sub', :setting => 'fleezy', :value => 'flam2'))
+      provider = described_class.new(resource)
+      provider.exists?.should be true
+      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
+  fleezy = flam2
+ ; yet another comment
+      EOS
+      )
+    end
+
+  end
+
+
+  context "when dealing settings that have a commented version present" do
+    let(:orig_content) {
+      <<-EOS
+     [section1]
+     # foo=foovalue
+     bar=barvalue
+     foo = foovalue2
+
+[section2]
+# foo = foovalue
+;bar=barvalue
+blah = blah
+#baz=
+      EOS
+    }
+
+    it "should add a new setting below a commented version of that setting" do
+      resource = Puppet::Type::Ini_setting.new(
+          common_params.merge(:section => 'section2', :setting => 'foo', :value => 'foo3'))
+      provider = described_class.new(resource)
+      provider.exists?.should be false
+      provider.create
+      validate_file(<<-EOS
+     [section1]
+     # foo=foovalue
+     bar=barvalue
+     foo = foovalue2
+
+[section2]
+# foo = foovalue
+foo = foo3
+;bar=barvalue
+blah = blah
+#baz=
+      EOS
+      )
+    end
+
+    it "should update an existing setting in place, even if there is a commented version of that setting" do
+      resource = Puppet::Type::Ini_setting.new(
+          common_params.merge(:section => 'section1', :setting => 'foo', :value => 'foo3'))
+      provider = described_class.new(resource)
+      provider.exists?.should be true
+      provider.create
+      validate_file(<<-EOS
+     [section1]
+     # foo=foovalue
+     bar=barvalue
+     foo = foo3
+
+[section2]
+# foo = foovalue
+;bar=barvalue
+blah = blah
+#baz=
+      EOS
+      )
+    end
+
+    it "should add a new setting below a commented version of that setting, respecting semicolons as comments" do
+      resource = Puppet::Type::Ini_setting.new(
+          common_params.merge(:section => 'section2', :setting => 'bar', :value => 'bar3'))
+      provider = described_class.new(resource)
+      provider.exists?.should be false
+      provider.create
+      validate_file(<<-EOS
+     [section1]
+     # foo=foovalue
+     bar=barvalue
+     foo = foovalue2
+
+[section2]
+# foo = foovalue
+;bar=barvalue
+bar=bar3
+blah = blah
+#baz=
+      EOS
+      )
+    end
+
+    it "should add a new setting below an empty commented version of that setting" do
+      resource = Puppet::Type::Ini_setting.new(
+          common_params.merge(:section => 'section2', :setting => 'baz', :value => 'bazvalue'))
+      provider = described_class.new(resource)
+      provider.exists?.should be false
+      provider.create
+      validate_file(<<-EOS
+     [section1]
+     # foo=foovalue
+     bar=barvalue
+     foo = foovalue2
+
+[section2]
+# foo = foovalue
+;bar=barvalue
+blah = blah
+#baz=
+baz=bazvalue
+      EOS
+      )
+    end
+
+    context 'when a section only contains comments' do
+     let(:orig_content) {
+      <<-EOS
+[section1]
+# foo=foovalue
+# bar=bar2
+EOS
+    }
+      it 'should be able to add a new setting when a section contains only comments' do
+        resource = Puppet::Type::Ini_setting.new(
+          common_params.merge(:section => 'section1', :setting => 'foo', :value => 'foovalue2')
+        )
+        provider = described_class.new(resource)
+        provider.exists?.should be false
+        provider.create
+        validate_file(<<-EOS
+[section1]
+# foo=foovalue
+foo=foovalue2
+# bar=bar2
+        EOS
+        )
+      end
+      it 'should be able to add a new setting when it matches a commented out line other than the first one' do
+        resource = Puppet::Type::Ini_setting.new(
+          common_params.merge(:section => 'section1', :setting => 'bar', :value => 'barvalue2')
+        )
+        provider = described_class.new(resource)
+        provider.exists?.should be false
+        provider.create
+        validate_file(<<-EOS
+[section1]
+# foo=foovalue
+# bar=bar2
+bar=barvalue2
+        EOS
+        )
+      end
+    end
+
+    context "when sections have spaces and dashes" do
+      let(:orig_content) {
+        <<-EOS
+# This is a comment
+[section - one]
+; This is also a comment
+foo=foovalue
+
+bar = barvalue
+master = true
+[section - two]
+
+foo= foovalue2
+baz=bazvalue
+url = http://192.168.1.1:8080
+[section:sub]
+subby=bar
+    #another comment
+ ; yet another comment
+        EOS
+      }
+
+      it "should add a missing setting to the correct section" do
+        resource = Puppet::Type::Ini_setting.new(common_params.merge(
+            :section => 'section - two', :setting => 'yahoo', :value => 'yippee'))
+        provider = described_class.new(resource)
+        provider.exists?.should be false
+        provider.create
+        validate_file(<<-EOS
+# This is a comment
+[section - one]
+; This is also a comment
+foo=foovalue
+
+bar = barvalue
+master = true
+[section - two]
+
+foo= foovalue2
+baz=bazvalue
+url = http://192.168.1.1:8080
+yahoo = yippee
+[section:sub]
+subby=bar
+    #another comment
+ ; yet another comment
+        EOS
+  )
+      end
+
+    end
+
+  end
+
+  context "when sections have spaces and quotations" do
+    let(:orig_content) do
+      <<-EOS
+[branch "master"]
+        remote = origin
+        merge = refs/heads/master
+
+[alias]
+to-deploy = log --merges --grep='pull request' --format='%s (%cN)' origin/production..origin/master
+[branch "production"]
+        remote = origin
+        merge = refs/heads/production
+      EOS
+    end
+
+    it "should add a missing setting to the correct section" do
+      resource = Puppet::Type::Ini_setting.new(common_params.merge(
+        :section => 'alias',
+        :setting => 'foo',
+        :value => 'bar'
+      ))
+      provider = described_class.new(resource)
+      provider.exists?.should be false
+      provider.create
+      validate_file(<<-EOS
+[branch "master"]
+        remote = origin
+        merge = refs/heads/master
+
+[alias]
+to-deploy = log --merges --grep='pull request' --format='%s (%cN)' origin/production..origin/master
+foo = bar
+[branch "production"]
+        remote = origin
+        merge = refs/heads/production
+                    EOS
+                   )
+    end
+
+  end
+
+end
diff --git a/3rdparty/modules/inifile/spec/unit/puppet/provider/ini_subsetting/ruby_spec.rb b/3rdparty/modules/inifile/spec/unit/puppet/provider/ini_subsetting/ruby_spec.rb
new file mode 100644 (file)
index 0000000..ebe55c0
--- /dev/null
@@ -0,0 +1,135 @@
+require 'spec_helper'
+require 'puppet'
+
+provider_class = Puppet::Type.type(:ini_subsetting).provider(:ruby)
+describe provider_class do
+  include PuppetlabsSpec::Files
+
+  let(:tmpfile) { tmpfilename("ini_setting_test") }
+
+  def validate_file(expected_content,tmpfile = tmpfile)
+    File.read(tmpfile).should == expected_content
+  end
+
+
+  before :each do
+    File.open(tmpfile, 'w') do |fh|
+      fh.write(orig_content)
+    end
+  end
+
+  context "when ensuring that a subsetting is present" do
+    let(:common_params) { {
+        :title    => 'ini_setting_ensure_present_test',
+        :path     => tmpfile,
+        :section  => '',
+        :key_val_separator => '=',
+        :setting => 'JAVA_ARGS',
+    } }
+
+    let(:orig_content) {
+      <<-EOS
+JAVA_ARGS="-Xmx192m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/pe-puppetdb/puppetdb-oom.hprof"
+      EOS
+    }
+
+    it "should add a missing subsetting" do
+      resource = Puppet::Type::Ini_subsetting.new(common_params.merge(
+         :subsetting => '-Xms', :value => '128m'))
+      provider = described_class.new(resource)
+      provider.exists?.should be_nil
+      provider.create
+      validate_file(<<-EOS
+JAVA_ARGS="-Xmx192m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/pe-puppetdb/puppetdb-oom.hprof -Xms128m"
+      EOS
+)
+    end
+
+    it "should remove an existing subsetting" do
+      resource = Puppet::Type::Ini_subsetting.new(common_params.merge(
+          :subsetting => '-Xmx'))
+      provider = described_class.new(resource)
+      provider.exists?.should == "192m"
+      provider.destroy
+      validate_file(<<-EOS
+JAVA_ARGS="-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/pe-puppetdb/puppetdb-oom.hprof"
+      EOS
+)
+    end
+    
+    it "should modify an existing subsetting" do
+      resource = Puppet::Type::Ini_subsetting.new(common_params.merge(
+          :subsetting => '-Xmx', :value => '256m'))
+      provider = described_class.new(resource)
+      provider.exists?.should == "192m"
+      provider.value=('256m')
+      validate_file(<<-EOS
+JAVA_ARGS="-Xmx256m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/pe-puppetdb/puppetdb-oom.hprof"
+      EOS
+)
+    end
+  end
+
+  context "when working with subsettings in files with unquoted settings values" do
+    let(:common_params) { {
+        :title    => 'ini_setting_ensure_present_test',
+        :path     => tmpfile,
+        :section  => 'master',
+        :setting => 'reports',
+    } }
+
+    let(:orig_content) {
+      <<-EOS
+[master]
+
+reports = http,foo
+      EOS
+    }
+
+    it "should remove an existing subsetting" do
+      resource = Puppet::Type::Ini_subsetting.new(common_params.merge(
+          :subsetting => 'http', :subsetting_separator => ','))
+      provider = described_class.new(resource)
+      provider.exists?.should == ""
+      provider.destroy
+      validate_file(<<-EOS
+[master]
+
+reports = foo
+      EOS
+      )
+    end
+
+    it "should add a new subsetting when the 'parent' setting already exists" do
+      resource = Puppet::Type::Ini_subsetting.new(common_params.merge(
+          :subsetting => 'puppetdb', :subsetting_separator => ','))
+      provider = described_class.new(resource)
+      provider.exists?.should be_nil
+      provider.value=('')
+      validate_file(<<-EOS
+[master]
+
+reports = http,foo,puppetdb
+      EOS
+      )
+    end
+
+    it "should add a new subsetting when the 'parent' setting does not already exist" do
+      resource = Puppet::Type::Ini_subsetting.new(common_params.merge(
+          :setting => 'somenewsetting',
+          :subsetting => 'puppetdb',
+          :subsetting_separator => ','))
+      provider = described_class.new(resource)
+      provider.exists?.should be_nil
+      provider.value=('')
+      validate_file(<<-EOS
+[master]
+
+reports = http,foo
+somenewsetting = puppetdb
+      EOS
+      )
+    end
+
+  end
+end
diff --git a/3rdparty/modules/inifile/spec/unit/puppet/util/external_iterator_spec.rb b/3rdparty/modules/inifile/spec/unit/puppet/util/external_iterator_spec.rb
new file mode 100644 (file)
index 0000000..92b17af
--- /dev/null
@@ -0,0 +1,35 @@
+require 'spec_helper'
+require 'puppet/util/external_iterator'
+
+describe Puppet::Util::ExternalIterator do
+  let(:subject) { Puppet::Util::ExternalIterator.new(["a", "b", "c"]) }
+
+  context "#next" do
+    it "should iterate over the items" do
+      subject.next.should == ["a", 0]
+      subject.next.should == ["b", 1]
+      subject.next.should == ["c", 2]      
+    end
+  end
+
+  context "#peek" do
+    it "should return the 0th item repeatedly" do
+      subject.peek.should == ["a", 0]
+      subject.peek.should == ["a", 0]
+    end
+    
+    it "should not advance the iterator, but should reflect calls to #next" do
+      subject.peek.should == ["a", 0]
+      subject.peek.should == ["a", 0]
+      subject.next.should == ["a", 0]
+      subject.peek.should == ["b", 1]
+      subject.next.should == ["b", 1]
+      subject.peek.should == ["c", 2]
+      subject.next.should == ["c", 2]
+      subject.peek.should == [nil, nil]
+      subject.next.should == [nil, nil]
+    end
+  end
+
+
+end
diff --git a/3rdparty/modules/inifile/spec/unit/puppet/util/ini_file_spec.rb b/3rdparty/modules/inifile/spec/unit/puppet/util/ini_file_spec.rb
new file mode 100644 (file)
index 0000000..7a92090
--- /dev/null
@@ -0,0 +1,287 @@
+require 'spec_helper'
+require 'stringio'
+require 'puppet/util/ini_file'
+
+describe Puppet::Util::IniFile do
+  let(:subject) { Puppet::Util::IniFile.new("/my/ini/file/path") }
+
+  before :each do
+    File.should_receive(:file?).with("/my/ini/file/path") { true }
+    described_class.should_receive(:readlines).once.with("/my/ini/file/path") do
+      sample_content
+    end
+  end
+
+  context "when parsing a file" do
+    let(:sample_content) {
+      template = <<-EOS
+# This is a comment
+[section1]
+; This is also a comment
+foo=foovalue
+
+bar = barvalue
+baz =
+[section2]
+
+foo= foovalue2
+baz=bazvalue
+ ; commented = out setting
+    #another comment
+ ; yet another comment
+ zot = multi word value
+ xyzzy['thing1']['thing2']=xyzzyvalue
+ l=git log
+      EOS
+      template.split("\n")
+    }
+
+    it "should parse the correct number of sections" do
+      # there is always a "global" section, so our count should be 3.
+      subject.section_names.length.should == 3
+    end
+
+    it "should parse the correct section_names" do
+      # there should always be a "global" section named "" at the beginning of the list
+      subject.section_names.should == ["", "section1", "section2"]
+    end
+
+    it "should expose settings for sections" do
+      subject.get_settings("section1").should == {
+        "bar" => "barvalue",
+        "baz" => "",
+        "foo" => "foovalue"
+      }
+
+      subject.get_settings("section2").should == {
+        "baz" => "bazvalue",
+        "foo" => "foovalue2",
+        "l" => "git log",
+        "xyzzy['thing1']['thing2']" => "xyzzyvalue",
+        "zot" => "multi word value"
+      }
+    end
+
+  end
+
+  context "when parsing a file whose first line is a section" do
+    let(:sample_content) {
+      template = <<-EOS
+[section1]
+; This is a comment
+foo=foovalue
+      EOS
+      template.split("\n")
+    }
+
+    it "should parse the correct number of sections" do
+      # there is always a "global" section, so our count should be 2.
+      subject.section_names.length.should == 2
+    end
+
+    it "should parse the correct section_names" do
+      # there should always be a "global" section named "" at the beginning of the list
+      subject.section_names.should == ["", "section1"]
+    end
+
+    it "should expose settings for sections" do
+      subject.get_value("section1", "foo").should == "foovalue"
+    end
+
+  end
+
+  context "when parsing a file with a 'global' section" do
+    let(:sample_content) {
+      template = <<-EOS
+foo = bar
+[section1]
+; This is a comment
+foo=foovalue
+      EOS
+      template.split("\n")
+    }
+
+    it "should parse the correct number of sections" do
+      # there is always a "global" section, so our count should be 2.
+      subject.section_names.length.should == 2
+    end
+
+    it "should parse the correct section_names" do
+      # there should always be a "global" section named "" at the beginning of the list
+      subject.section_names.should == ["", "section1"]
+    end
+
+    it "should expose settings for sections" do
+      subject.get_value("", "foo").should == "bar"
+      subject.get_value("section1", "foo").should == "foovalue"
+    end
+  end
+
+  context "when updating a file with existing empty values" do
+    let(:sample_content) {
+      template = <<-EOS
+[section1]
+foo=
+#bar=
+#xyzzy['thing1']['thing2']='xyzzyvalue'
+      EOS
+      template.split("\n")
+    }
+
+    it "should properly update uncommented values" do
+      subject.get_value("section1", "far").should == nil
+      subject.set_value("section1", "foo", "foovalue")
+      subject.get_value("section1", "foo").should == "foovalue"
+    end
+
+    it "should properly update commented values" do
+      subject.get_value("section1", "bar").should == nil
+      subject.set_value("section1", "bar", "barvalue")
+      subject.get_value("section1", "bar").should == "barvalue"
+      subject.get_value("section1", "xyzzy['thing1']['thing2']").should == nil
+      subject.set_value("section1", "xyzzy['thing1']['thing2']", "xyzzyvalue")
+      subject.get_value("section1", "xyzzy['thing1']['thing2']").should == "xyzzyvalue"
+    end
+
+    it "should properly add new empty values" do
+      subject.get_value("section1", "baz").should == nil
+      subject.set_value("section1", "baz", "bazvalue")
+      subject.get_value("section1", "baz").should == "bazvalue"
+    end
+  end
+
+  context 'the file has quotation marks in its section names' do
+    let(:sample_content) do
+      template = <<-EOS
+[branch "master"]
+        remote = origin
+        merge = refs/heads/master
+
+[alias]
+to-deploy = log --merges --grep='pull request' --format='%s (%cN)' origin/production..origin/master
+[branch "production"]
+        remote = origin
+        merge = refs/heads/production
+      EOS
+      template.split("\n")
+    end
+
+    it 'should parse the sections' do
+      subject.section_names.should match_array ['',
+                                                'branch "master"',
+                                                'alias',
+                                                'branch "production"'
+      ]
+    end
+  end
+
+  context 'Samba INI file with dollars in section names' do
+    let(:sample_content) do
+      template = <<-EOS
+      [global]
+        workgroup = FELLOWSHIP
+        ; ...
+        idmap config * : backend = tdb
+
+      [printers]
+        comment = All Printers
+        ; ...
+        browseable = No
+
+      [print$]
+        comment = Printer Drivers
+        path = /var/lib/samba/printers
+
+      [Shares]
+        path = /home/shares
+        read only = No
+        guest ok = Yes
+      EOS
+      template.split("\n")
+    end
+
+    it "should parse the correct section_names" do
+      subject.section_names.should match_array [
+        '',
+        'global',
+        'printers',
+        'print$',
+        'Shares'
+      ]
+    end
+  end
+
+  context 'section names with forward slashes in them' do
+    let(:sample_content) do
+      template = <<-EOS
+[monitor:///var/log/*.log]
+disabled = test_value
+      EOS
+      template.split("\n")
+    end
+
+    it "should parse the correct section_names" do
+      subject.section_names.should match_array [
+        '',
+        'monitor:///var/log/*.log'
+      ]
+    end
+  end
+
+  context 'KDE Configuration with braces in setting names' do
+    let(:sample_content) do
+      template = <<-EOS
+      [khotkeys]
+_k_friendly_name=khotkeys
+{5465e8c7-d608-4493-a48f-b99d99fdb508}=Print,none,PrintScreen
+{d03619b6-9b3c-48cc-9d9c-a2aadb485550}=Search,none,Search
+EOS
+      template.split("\n")
+    end
+
+    it "should expose settings for sections" do
+      subject.get_value("khotkeys", "{5465e8c7-d608-4493-a48f-b99d99fdb508}").should == "Print,none,PrintScreen"
+      subject.get_value("khotkeys", "{d03619b6-9b3c-48cc-9d9c-a2aadb485550}").should == "Search,none,Search"
+    end
+  end
+
+  context 'Configuration with colons in setting names' do
+    let(:sample_content) do
+      template = <<-EOS
+      [Drive names]
+A:=5.25" Floppy
+B:=3.5" Floppy
+C:=Winchester
+EOS
+      template.split("\n")
+    end
+
+    it "should expose settings for sections" do
+      subject.get_value("Drive names", "A:").should eq '5.25" Floppy'
+      subject.get_value("Drive names", "B:").should eq '3.5" Floppy'
+      subject.get_value("Drive names", "C:").should eq 'Winchester'
+    end
+  end
+
+  context 'Configuration with spaces in setting names' do
+    let(:sample_content) do
+      template = <<-EOS
+      [global]
+        # log files split per-machine:
+        log file = /var/log/samba/log.%m
+
+        kerberos method = system keytab
+        passdb backend = tdbsam
+        security = ads
+EOS
+      template.split("\n")
+    end
+
+    it "should expose settings for sections" do
+      subject.get_value("global", "log file").should eq '/var/log/samba/log.%m'
+      subject.get_value("global", "kerberos method").should eq 'system keytab'
+      subject.get_value("global", "passdb backend").should eq 'tdbsam'
+      subject.get_value("global", "security").should eq 'ads'
+    end
+  end
+end
diff --git a/3rdparty/modules/inifile/spec/unit/puppet/util/setting_value_spec.rb b/3rdparty/modules/inifile/spec/unit/puppet/util/setting_value_spec.rb
new file mode 100644 (file)
index 0000000..8514724
--- /dev/null
@@ -0,0 +1,103 @@
+require 'spec_helper'
+require 'puppet/util/setting_value'
+
+describe Puppet::Util::SettingValue do
+
+  describe "space subsetting separator" do
+    INIT_VALUE_SPACE = "\"-Xmx192m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/pe-puppetdb/puppetdb-oom.hprof\""
+
+    before :each do
+      @setting_value = Puppet::Util::SettingValue.new(INIT_VALUE_SPACE, " ")
+    end
+  
+    it "should get the original value" do
+      @setting_value.get_value.should == INIT_VALUE_SPACE
+    end
+   
+    it "should get the correct value" do
+      @setting_value.get_subsetting_value("-Xmx").should == "192m"
+    end
+  
+    it "should add a new value" do
+      @setting_value.add_subsetting("-Xms", "256m")
+      @setting_value.get_subsetting_value("-Xms").should == "256m"
+      @setting_value.get_value.should == INIT_VALUE_SPACE[0, INIT_VALUE_SPACE.length - 1] + " -Xms256m\""
+    end
+  
+    it "should change existing value" do
+      @setting_value.add_subsetting("-Xmx", "512m")
+      @setting_value.get_subsetting_value("-Xmx").should == "512m"
+    end
+  
+    it "should remove existing value" do
+      @setting_value.remove_subsetting("-Xmx")
+      @setting_value.get_subsetting_value("-Xmx").should == nil
+    end
+  end
+
+  describe "comma subsetting separator" do
+    INIT_VALUE_COMMA = "\"-Xmx192m,-XX:+HeapDumpOnOutOfMemoryError,-XX:HeapDumpPath=/var/log/pe-puppetdb/puppetdb-oom.hprof\""
+
+    before :each do
+      @setting_value = Puppet::Util::SettingValue.new(INIT_VALUE_COMMA, ",")
+    end
+  
+    it "should get the original value" do
+      @setting_value.get_value.should == INIT_VALUE_COMMA
+    end
+   
+    it "should get the correct value" do
+      @setting_value.get_subsetting_value("-Xmx").should == "192m"
+    end
+  
+    it "should add a new value" do
+      @setting_value.add_subsetting("-Xms", "256m")
+      @setting_value.get_subsetting_value("-Xms").should == "256m"
+      @setting_value.get_value.should == INIT_VALUE_COMMA[0, INIT_VALUE_COMMA.length - 1] + ",-Xms256m\""
+    end
+  
+    it "should change existing value" do
+      @setting_value.add_subsetting("-Xmx", "512m")
+      @setting_value.get_subsetting_value("-Xmx").should == "512m"
+    end
+  
+    it "should remove existing value" do
+      @setting_value.remove_subsetting("-Xmx")
+      @setting_value.get_subsetting_value("-Xmx").should == nil
+    end
+  end
+
+  describe "quote_char parameter" do
+    QUOTE_CHAR = '"'
+    INIT_VALUE_UNQUOTED = '-Xmx192m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/pe-puppetdb/puppetdb-oom.hprof'
+
+    it "should get quoted empty string if original value was empty" do
+      setting_value = Puppet::Util::SettingValue.new(nil, ' ', QUOTE_CHAR)
+      setting_value.get_value.should == QUOTE_CHAR * 2
+    end
+   
+    it "should quote the setting when adding a value" do
+      setting_value = Puppet::Util::SettingValue.new(INIT_VALUE_UNQUOTED, ' ', QUOTE_CHAR)
+      setting_value.add_subsetting("-Xms", "256m")
+
+      setting_value.get_subsetting_value("-Xms").should == "256m"
+      setting_value.get_value.should == QUOTE_CHAR + INIT_VALUE_UNQUOTED + ' -Xms256m' + QUOTE_CHAR
+    end
+  
+    it "should quote the setting when changing an existing value" do
+      setting_value = Puppet::Util::SettingValue.new(INIT_VALUE_UNQUOTED, ' ', QUOTE_CHAR)
+      setting_value.add_subsetting("-Xmx", "512m")
+
+      setting_value.get_subsetting_value("-Xmx").should == "512m"
+      setting_value.get_value.should =~ /^#{Regexp.quote(QUOTE_CHAR)}.*#{Regexp.quote(QUOTE_CHAR)}$/
+    end
+  
+    it "should quote the setting when removing an existing value" do
+      setting_value = Puppet::Util::SettingValue.new(INIT_VALUE_UNQUOTED, ' ', QUOTE_CHAR)
+      setting_value.remove_subsetting("-Xmx")
+
+      setting_value.get_subsetting_value("-Xmx").should == nil
+      setting_value.get_value.should =~ /^#{Regexp.quote(QUOTE_CHAR)}.*#{Regexp.quote(QUOTE_CHAR)}$/
+    end
+  end
+end
diff --git a/3rdparty/modules/inifile/tests/ini_setting.pp b/3rdparty/modules/inifile/tests/ini_setting.pp
new file mode 100644 (file)
index 0000000..279cb00
--- /dev/null
@@ -0,0 +1,25 @@
+ini_setting { 'sample setting':
+  ensure  => present,
+  path    => '/tmp/foo.ini',
+  section => 'foo',
+  setting => 'foosetting',
+  value   => 'FOO!',
+}
+
+ini_setting { 'sample setting2':
+  ensure            => present,
+  path              => '/tmp/foo.ini',
+  section           => 'bar',
+  setting           => 'barsetting',
+  value             => 'BAR!',
+  key_val_separator => '=',
+  require           => Ini_setting['sample setting'],
+}
+
+ini_setting { 'sample setting3':
+  ensure  => absent,
+  path    => '/tmp/foo.ini',
+  section => 'bar',
+  setting => 'bazsetting',
+  require => Ini_setting['sample setting2'],
+}
diff --git a/3rdparty/modules/inifile/tests/ini_subsetting.pp b/3rdparty/modules/inifile/tests/ini_subsetting.pp
new file mode 100644 (file)
index 0000000..0458354
--- /dev/null
@@ -0,0 +1,18 @@
+ini_subsetting { 'sample subsetting':
+  ensure            => present,
+  section           => '',
+  key_val_separator => '=',
+  path              => '/etc/default/pe-puppetdb',
+  setting           => 'JAVA_ARGS',
+  subsetting        => '-Xmx',
+  value             => '512m',
+}
+
+ini_subsetting { 'sample subsetting2':
+  ensure            => absent,
+  section           => '',
+  key_val_separator => '=',
+  path              => '/etc/default/pe-puppetdb',
+  setting           => 'JAVA_ARGS',
+  subsetting        => '-Xms',
+}