puppetlabs-inifile-1.4.2/000755 000766 000024 00000000000 12571433714 015560 5ustar00bmjenstaff000000 000000 puppetlabs-inifile-1.4.2/CHANGELOG.md000644 000766 000024 00000015317 12571433667 017407 0ustar00bmjenstaff000000 000000 ## 2015-09-01 - Supported Release 1.4.2 ### Summary This release adds some bugfixes. ####Bugfixes - MODULES-2212 Add use_exact_match parameter for subsettings - MODULES-1908 Munge the setting to ensure we always strip the whitespace - MODULES-2369 Support a space as a key_val_separator ## 2015-07-15 - Supported Release 1.4.1 ### Summary This release bumps the metadata for PE up. ##2015-07-07 - Supported Releases 1.4.0 ###Summary This is primarily a release which includes acceptance tests updates, but also includes some minor bug fixes and improvements ####Features - Solaris 12 Support - Acceptance testing improvements ####Bugfixes - MODULES-1599 Match only on space and tab whitespace after k/v separator ##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 - 0.10.3 * Fix bug in subsetting handling for new settings (cbea5dc) ##2013-05-22 - Chris Price - 0.10.2 * Better handling of quotes for subsettings (1aa7e60) ##2013-05-21 - Chris Price - 0.10.1 * Change constants to class variables to avoid ruby warnings (6b19864) ##2013-04-10 - Erik Dalén - 0.10.1 * Style fixes (c4af8c3) ##2013-04-02 - Dan Bode - 0.10.1 * Add travisfile and Gemfile (c2052b3) ##2013-04-02 - Chris Price - 0.10.1 * Update README.markdown (ad38a08) ##2013-02-15 - Karel Brezina - 0.10.0 * Added 'ini_subsetting' custom resource type (4351d8b) ##2013-03-11 - Dan Bode - 0.10.0 * guard against nil indentation values (5f71d7f) ##2013-01-07 - Dan Bode - 0.10.0 * Add purging support to ini file (2f22483) ##2013-02-05 - James Sweeny - 0.10.0 * Fix test to use correct key_val_parameter (b1aff63) ##2012-11-06 - Chris Price - 0.10.0 * Added license file w/Apache 2.0 license (5e1d203) ##2012-11-02 - Chris Price - 0.9.0 * Version 0.9.0 released ##2012-10-26 - Chris Price - 0.9.0 * Add detection for commented versions of settings (a45ab65) ##2012-10-20 - Chris Price - 0.9.0 * Refactor to clarify implementation of `save` (f0d443f) ##2012-10-20 - Chris Price - 0.9.0 * Add example for `ensure=absent` (e517148) ##2012-10-20 - Chris Price - 0.9.0 * Better handling of whitespace lines at ends of sections (845fa70) ##2012-10-20 - Chris Price - 0.9.0 * Respect indentation / spacing for existing sections and settings (c2c26de) ##2012-10-17 - Chris Price - 0.9.0 * Minor tweaks to handling of removing settings (cda30a6) ##2012-10-10 - Dan Bode - 0.9.0 * Add support for removing lines (1106d70) ##2012-10-02 - Dan Bode - 0.9.0 * Make value a property (cbc90d3) ##2012-10-02 - Dan Bode - 0.9.0 * Make ruby provider a better parent. (1564c47) ##2012-09-29 - Reid Vandewiele - 0.9.0 * Allow values with spaces to be parsed and set (3829e20) ##2012-09-24 - Chris Price - 0.0.3 * Version 0.0.3 released ##2012-09-20 - Chris Price - 0.0.3 * Add validation for key_val_separator (e527908) ##2012-09-19 - Chris Price - 0.0.3 * Allow overriding separator string between key/val pairs (8d1fdc5) ##2012-08-20 - Chris Price - 0.0.2 * Version 0.0.2 released ##2012-08-17 - Chris Price - 0.0.2 * Add support for "global" section at beginning of file (c57dab4) puppetlabs-inifile-1.4.2/checksums.json000644 000766 000024 00000007646 12571433714 020455 0ustar00bmjenstaff000000 000000 { "CHANGELOG.md": "bb1713e35d5ef7a93dfd4b5aa3ee980e", "CONTRIBUTING.md": "ad65d271f183b5adb9fdd58207939f5f", "Gemfile": "fb50030e28db2a30561badca2e474c1e", "LICENSE": "519b25a3992e0598a9855e4ccd7f66a1", "README.markdown": "4e860c5d106005dbaab34a1fb362ec49", "Rakefile": "d953eb985f82600dc3b9ac6e1f2cfe64", "examples/ini_setting.pp": "9c8a9d2c453901cedb106cada253f1f6", "examples/ini_subsetting.pp": "71c82234fa8bb8cb442ff01436ce2cf3", "lib/puppet/parser/functions/create_ini_settings.rb": "c5d2c4531f93395ce0e6c604a816a0bb", "lib/puppet/provider/ini_setting/ruby.rb": "194c03eab6111e5eb6668ee847cdabcf", "lib/puppet/provider/ini_subsetting/ruby.rb": "aef090b9b38f80b9dc70abacd26365ab", "lib/puppet/type/ini_setting.rb": "378f183dcf61d65e0a74cccfa1a49084", "lib/puppet/type/ini_subsetting.rb": "0e3bc0a4b63c0a8f4eefb57547f5c67f", "lib/puppet/util/external_iterator.rb": "69ad1eb930ca6d8d6b6faea343b4a22e", "lib/puppet/util/ini_file/section.rb": "77757399ed9b9ce352ddcc8b8f9273c4", "lib/puppet/util/ini_file.rb": "d83db0406006cff7113891ec163e2a43", "lib/puppet/util/setting_value.rb": "e8c380aa3e41e0c6d11f8110ee0344bd", "metadata.json": "d3ff4c0c0b314766455a743734cdd8bf", "spec/acceptance/ini_setting_spec.rb": "f4fe5b9e18748ed2d7a92c9d7ec525b6", "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": "74f51e1ce2766dcd7c338d6e8e70626d", "spec/unit/puppet/provider/ini_setting/inheritance_spec.rb": "bbe2fb9d6805ae8cae85271e48f646b3", "spec/unit/puppet/provider/ini_setting/ruby_spec.rb": "479c7338d5e99705f9ec829c83f8c725", "spec/unit/puppet/provider/ini_subsetting/ruby_spec.rb": "20a3ea0d5acea0b496f3681e93a19a41", "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" }puppetlabs-inifile-1.4.2/CONTRIBUTING.md000644 000766 000024 00000017501 12571432054 020011 0ustar00bmjenstaff000000 000000 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 % bundle exec 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 % bundle exec rake spec_clean % bundle exec 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/) puppetlabs-inifile-1.4.2/examples/000755 000766 000024 00000000000 12571433714 017376 5ustar00bmjenstaff000000 000000 puppetlabs-inifile-1.4.2/Gemfile000644 000766 000024 00000002520 12571432054 017046 0ustar00bmjenstaff000000 000000 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 gem 'beaker-puppet_install_helper', :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 puppetlabs-inifile-1.4.2/lib/000755 000766 000024 00000000000 12571433714 016326 5ustar00bmjenstaff000000 000000 puppetlabs-inifile-1.4.2/LICENSE000644 000766 000024 00000026114 12571432054 016565 0ustar00bmjenstaff000000 000000 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. puppetlabs-inifile-1.4.2/metadata.json000644 000766 000024 00000003717 12571433714 020243 0ustar00bmjenstaff000000 000000 { "name": "puppetlabs-inifile", "version": "1.4.2", "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", "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", "12" ] }, { "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.0.0 < 2015.3.0" }, { "name": "puppet", "version_requirement": ">= 3.0.0 < 5.0.0" } ], "dependencies": [ ] } puppetlabs-inifile-1.4.2/Rakefile000644 000766 000024 00000000766 12571432054 017232 0ustar00bmjenstaff000000 000000 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"] puppetlabs-inifile-1.4.2/README.markdown000644 000766 000024 00000027063 12571433667 020300 0ustar00bmjenstaff000000 000000 #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: ~~~puppet 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: ~~~puppet ini_subsetting {'sample subsetting': ensure => present, section => '', key_val_separator => '=', path => '/etc/default/pe-puppetdb', setting => 'JAVA_ARGS', subsetting => '-Xmx', value => '512m', } ~~~ Results in managing this `-Xmx` subsetting: ~~~puppet JAVA_ARGS="-Xmx512m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/pe-puppetdb/puppetdb-oom.hprof" ~~~ ###Use a non-standard section header ~~~puppet ini_setting { 'default minage': ensure => present, path => '/etc/security/users', section => 'default', setting => 'minage', value => '1', section_prefix => '', section_suffix => ':', } ~~~ Results in: ~~~puppet default: minage = 1 ~~~ ###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`: ~~~ruby #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: ~~~ruby # 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: ~~~puppet 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: ~~~puppet resources { 'glance_api_config' purge => true, } ~~~ ### Manage multiple ini_settings To manage multiple ini_settings, use the [`create_ini_settings`](#function-create_ini_settings) function. ~~~puppet $defaults = { 'path' => '/tmp/foo.ini' } $example = { 'section1' => { 'setting1' => 'value1' } } create_ini_settings($example, $defaults) ~~~ results in: ~~~puppet ini_setting { '[section1] setting1': ensure => present, section => 'section1', setting => 'setting1', value => 'value1', path => '/tmp/foo.ini', } ~~~ To include special parameters, the following code: ~~~puppet $defaults = { 'path' => '/tmp/foo.ini' } $example = { 'section1' => { 'setting1' => 'value1', 'settings2' => { 'ensure' => 'absent' } } } create_ini_settings($example, $defaults) ~~~ results in: ~~~puppet ini_setting { '[section1] setting1': ensure => present, section => 'section1', setting => 'setting1', value => 'value1', path => '/tmp/foo.ini', } ini_setting { '[section1] setting2': ensure => absent, section => 'section1', setting => 'setting2', path => '/tmp/foo.ini', } ~~~ #### Manage multiple ini_settings with Hiera This example requires Puppet 3.x/4.x, as it uses automatic retrieval of Hiera data for class parameters and `puppetlabs/stdlib`. For the profile `example`: ~~~puppet class profile::example ( $settings, ) { validate_hash($settings) $defaults = { 'path' => '/tmp/foo.ini' } create_ini_settings($settings, $defaults) } ~~~ Provide this in your Hiera data: ~~~puppet profile::example::settings: section1: setting1: value1 setting2: value2 setting3: ensure: absent ~~~ Results in: ~~~puppet ini_setting { '[section1] setting1': ensure => present, section => 'section1', setting => 'setting1', value => 'value1', path => '/tmp/foo.ini', } ini_setting { '[section1] setting2': ensure => present, section => 'section1', setting => 'setting2', value => 'value2', path => '/tmp/foo.ini', } ini_setting { '[section1] setting3': ensure => absent, section => 'section1', setting => 'setting3', path => '/tmp/foo.ini', } ~~~ ##Reference ###Public Types * [`ini_setting`](#type-ini_setting) * [`ini_subsetting`](#type-ini_subsetting) ###Public Functions * [`create_ini_settings`](#function-create_ini_settings) ### 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.* The name of the setting to define. 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:** This type finds all sections in the file 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 setting 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: " ". ##### `use_exact_match` *Optional.* Whether to use partial or exact matching for subsetting. Should be set to true if the subsettings do not have values. Valid options: true, false. Default value: false. ##### `value` *Optional.* Supplies a value for the specified subsetting. Valid options: a string. Default value: undefined. ### Function: create_ini_settings Manages multiple `ini_setting` resources from a hash. Note that this cannot be used with ini_subsettings. `create_ini_settings($settings, $defaults)` #### Arguments ##### First argument: `settings` *Required.* Specify a hash representing the `ini_setting` resources you want to create. ##### Second argument: `defaults` *Optional.* Accepts a hash to be used as the values for any attributes not defined in the first argument. ~~~puppet $example = { 'section1' => { 'setting1' => { 'value' => 'value1', 'path' => '/tmp/foo.ini' } } } ~~~ Default value: '{}'. ##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, Mac OS X 10.9, and Solaris 12. ##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) puppetlabs-inifile-1.4.2/spec/000755 000766 000024 00000000000 12571433714 016512 5ustar00bmjenstaff000000 000000 puppetlabs-inifile-1.4.2/spec/acceptance/000755 000766 000024 00000000000 12571433714 020600 5ustar00bmjenstaff000000 000000 puppetlabs-inifile-1.4.2/spec/classes/000755 000766 000024 00000000000 12571433714 020147 5ustar00bmjenstaff000000 000000 puppetlabs-inifile-1.4.2/spec/functions/000755 000766 000024 00000000000 12571433714 020522 5ustar00bmjenstaff000000 000000 puppetlabs-inifile-1.4.2/spec/spec.opts000644 000766 000024 00000000057 12571432054 020351 0ustar00bmjenstaff000000 000000 --format s --colour --loadby mtime --backtrace puppetlabs-inifile-1.4.2/spec/spec_helper.rb000644 000766 000024 00000000157 12571432054 021327 0ustar00bmjenstaff000000 000000 require 'puppetlabs_spec_helper/module_spec_helper' RSpec.configure do |config| config.mock_with :rspec end puppetlabs-inifile-1.4.2/spec/spec_helper_acceptance.rb000644 000766 000024 00000001126 12571432054 023472 0ustar00bmjenstaff000000 000000 require 'beaker-rspec/spec_helper' require 'beaker-rspec/helpers/serverspec' require 'beaker/puppet_install_helper' run_puppet_install_helper 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 puppetlabs-inifile-1.4.2/spec/unit/000755 000766 000024 00000000000 12571433714 017471 5ustar00bmjenstaff000000 000000 puppetlabs-inifile-1.4.2/spec/unit/puppet/000755 000766 000024 00000000000 12571433714 021006 5ustar00bmjenstaff000000 000000 puppetlabs-inifile-1.4.2/spec/unit/puppet/provider/000755 000766 000024 00000000000 12571433714 022640 5ustar00bmjenstaff000000 000000 puppetlabs-inifile-1.4.2/spec/unit/puppet/util/000755 000766 000024 00000000000 12571433714 021763 5ustar00bmjenstaff000000 000000 puppetlabs-inifile-1.4.2/spec/unit/puppet/util/external_iterator_spec.rb000644 000766 000024 00000001726 12571432054 027057 0ustar00bmjenstaff000000 000000 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 puppetlabs-inifile-1.4.2/spec/unit/puppet/util/ini_file_spec.rb000644 000766 000024 00000017353 12571432054 025105 0ustar00bmjenstaff000000 000000 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 puppetlabs-inifile-1.4.2/spec/unit/puppet/util/setting_value_spec.rb000644 000766 000024 00000007463 12571432054 026201 0ustar00bmjenstaff000000 000000 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 puppetlabs-inifile-1.4.2/spec/unit/puppet/provider/ini_setting/000755 000766 000024 00000000000 12571433714 025154 5ustar00bmjenstaff000000 000000 puppetlabs-inifile-1.4.2/spec/unit/puppet/provider/ini_subsetting/000755 000766 000024 00000000000 12571433714 025666 5ustar00bmjenstaff000000 000000 puppetlabs-inifile-1.4.2/spec/unit/puppet/provider/ini_subsetting/ruby_spec.rb000644 000766 000024 00000011566 12571432054 030213 0ustar00bmjenstaff000000 000000 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 context "when working with subsettings in files with use_exact_match" do let(:common_params) { { :title => 'ini_setting_ensure_present_test', :path => tmpfile, :section => 'master', :setting => 'reports', :use_exact_match => true, } } let(:orig_content) { <<-EOS [master] reports = http,foo EOS } it "should add a new subsetting when the 'parent' setting already exists" do resource = Puppet::Type::Ini_subsetting.new(common_params.merge( :subsetting => 'fo', :subsetting_separator => ',')) provider = described_class.new(resource) provider.value=('') validate_file(<<-eos [master] reports = http,foo,fo eos ) end it "should not remove substring subsettings" do resource = Puppet::Type::Ini_subsetting.new(common_params.merge( :subsetting => 'fo', :subsetting_separator => ',')) provider = described_class.new(resource) provider.value=('') provider.destroy validate_file(<<-EOS [master] reports = http,foo EOS ) end end end puppetlabs-inifile-1.4.2/spec/unit/puppet/provider/ini_setting/inheritance_spec.rb000644 000766 000024 00000003450 12571432054 031002 0ustar00bmjenstaff000000 000000 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 puppetlabs-inifile-1.4.2/spec/unit/puppet/provider/ini_setting/ruby_spec.rb000644 000766 000024 00000104361 12571432054 027475 0ustar00bmjenstaff000000 000000 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 overriding the separator to a space" 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 puppetlabs-inifile-1.4.2/spec/functions/create_ini_settings_spec.rb000644 000766 000024 00000001536 12571433667 026117 0ustar00bmjenstaff000000 000000 #! /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 puppetlabs-inifile-1.4.2/spec/classes/create_ini_settings_test_spec.rb000644 000766 000024 00000001374 12571433667 026603 0ustar00bmjenstaff000000 000000 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 puppetlabs-inifile-1.4.2/spec/classes/inherit_test1_spec.rb000644 000766 000024 00000000370 12571432054 024264 0ustar00bmjenstaff000000 000000 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 puppetlabs-inifile-1.4.2/spec/acceptance/ini_setting_spec.rb000644 000766 000024 00000020765 12571432054 024461 0ustar00bmjenstaff000000 000000 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 '=> present for global and section (from previous blank value)' do before :all do if fact('osfamily') == 'Darwin' shell("echo \"four =[one]\ntwo =\" > #{tmpdir}/ini_setting.ini") else shell("echo -e \"four =\n[one]\ntwo =\" > #{tmpdir}/ini_setting.ini") end end 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/, "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 puppetlabs-inifile-1.4.2/spec/acceptance/ini_subsetting_spec.rb000644 000766 000024 00000014034 12571432054 025163 0ustar00bmjenstaff000000 000000 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 puppetlabs-inifile-1.4.2/spec/acceptance/nodesets/000755 000766 000024 00000000000 12571433714 022424 5ustar00bmjenstaff000000 000000 puppetlabs-inifile-1.4.2/spec/acceptance/nodesets/centos-510-x64.yml000644 000766 000024 00000000377 12571432054 025367 0ustar00bmjenstaff000000 000000 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 puppetlabs-inifile-1.4.2/spec/acceptance/nodesets/centos-59-x64.yml000644 000766 000024 00000000370 12571432054 025310 0ustar00bmjenstaff000000 000000 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 puppetlabs-inifile-1.4.2/spec/acceptance/nodesets/centos-64-x64-pe.yml000644 000766 000024 00000000432 12571432054 025705 0ustar00bmjenstaff000000 000000 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 puppetlabs-inifile-1.4.2/spec/acceptance/nodesets/centos-64-x64.yml000644 000766 000024 00000000370 12571432054 025304 0ustar00bmjenstaff000000 000000 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 puppetlabs-inifile-1.4.2/spec/acceptance/nodesets/centos-65-x64.yml000644 000766 000024 00000000372 12571432054 025307 0ustar00bmjenstaff000000 000000 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 puppetlabs-inifile-1.4.2/spec/acceptance/nodesets/debian-607-x64.yml000644 000766 000024 00000000376 12571432054 025324 0ustar00bmjenstaff000000 000000 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 puppetlabs-inifile-1.4.2/spec/acceptance/nodesets/debian-73-x64.yml000644 000766 000024 00000000377 12571432054 025242 0ustar00bmjenstaff000000 000000 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 puppetlabs-inifile-1.4.2/spec/acceptance/nodesets/default.yml000644 000766 000024 00000000370 12571432054 024567 0ustar00bmjenstaff000000 000000 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 puppetlabs-inifile-1.4.2/spec/acceptance/nodesets/fedora-18-x64.yml000644 000766 000024 00000000375 12571432054 025255 0ustar00bmjenstaff000000 000000 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 puppetlabs-inifile-1.4.2/spec/acceptance/nodesets/sles-11sp1-x64.yml000644 000766 000024 00000000376 12571432054 025401 0ustar00bmjenstaff000000 000000 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 puppetlabs-inifile-1.4.2/spec/acceptance/nodesets/ubuntu-server-10044-x64.yml000644 000766 000024 00000000436 12571432054 027061 0ustar00bmjenstaff000000 000000 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 puppetlabs-inifile-1.4.2/spec/acceptance/nodesets/ubuntu-server-12042-x64.yml000644 000766 000024 00000000436 12571432054 027061 0ustar00bmjenstaff000000 000000 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 puppetlabs-inifile-1.4.2/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml000644 000766 000024 00000000420 12571432054 026772 0ustar00bmjenstaff000000 000000 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 puppetlabs-inifile-1.4.2/spec/acceptance/nodesets/windows-2003-i386.yml000644 000766 000024 00000001136 12571432054 025707 0ustar00bmjenstaff000000 000000 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/ puppetlabs-inifile-1.4.2/spec/acceptance/nodesets/windows-2003r2-x86_64.yml000644 000766 000024 00000001152 12571432054 026416 0ustar00bmjenstaff000000 000000 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/ puppetlabs-inifile-1.4.2/spec/acceptance/nodesets/windows-2008-x86_64.yml000644 000766 000024 00000001144 12571432054 026160 0ustar00bmjenstaff000000 000000 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/ puppetlabs-inifile-1.4.2/spec/acceptance/nodesets/windows-2008r2-x86_64.yml000644 000766 000024 00000001143 12571432054 026423 0ustar00bmjenstaff000000 000000 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/ puppetlabs-inifile-1.4.2/spec/acceptance/nodesets/windows-2012-x86_64.yml000644 000766 000024 00000001135 12571432054 026153 0ustar00bmjenstaff000000 000000 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/ puppetlabs-inifile-1.4.2/spec/acceptance/nodesets/windows-2012r2-x86_64.yml000644 000766 000024 00000001143 12571432054 026416 0ustar00bmjenstaff000000 000000 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/ puppetlabs-inifile-1.4.2/lib/puppet/000755 000766 000024 00000000000 12571433714 017643 5ustar00bmjenstaff000000 000000 puppetlabs-inifile-1.4.2/lib/puppet/parser/000755 000766 000024 00000000000 12571433714 021137 5ustar00bmjenstaff000000 000000 puppetlabs-inifile-1.4.2/lib/puppet/provider/000755 000766 000024 00000000000 12571433714 021475 5ustar00bmjenstaff000000 000000 puppetlabs-inifile-1.4.2/lib/puppet/type/000755 000766 000024 00000000000 12571433714 020624 5ustar00bmjenstaff000000 000000 puppetlabs-inifile-1.4.2/lib/puppet/util/000755 000766 000024 00000000000 12571433714 020620 5ustar00bmjenstaff000000 000000 puppetlabs-inifile-1.4.2/lib/puppet/util/external_iterator.rb000644 000766 000024 00000000641 12571432054 024675 0ustar00bmjenstaff000000 000000 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 puppetlabs-inifile-1.4.2/lib/puppet/util/ini_file/000755 000766 000024 00000000000 12571433714 022376 5ustar00bmjenstaff000000 000000 puppetlabs-inifile-1.4.2/lib/puppet/util/ini_file.rb000644 000766 000024 00000025756 12571432054 022736 0ustar00bmjenstaff000000 000000 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 =~ /^\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}[ \t]*)(.*)\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 puppetlabs-inifile-1.4.2/lib/puppet/util/setting_value.rb000644 000766 000024 00000005551 12571432054 024020 0ustar00bmjenstaff000000 000000 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, use_exact_match=:false) value = nil @subsetting_items.each { |item| if(use_exact_match == :false and item.start_with?(subsetting)) value = item[subsetting.length, item.length - subsetting.length] break elsif(use_exact_match == :true and item.eql?(subsetting)) return true end } value end def add_subsetting(subsetting, subsetting_value, use_exact_match=:false) new_item = subsetting + (subsetting_value || '') found = false @subsetting_items.map! { |item| if use_exact_match == :false and item.start_with?(subsetting) value = new_item found = true elsif use_exact_match == :true and item.eql?(subsetting) value = new_item found = true else value = item end value } unless found @subsetting_items.push(new_item) end end def remove_subsetting(subsetting, use_exact_match=:false) if use_exact_match == :false @subsetting_items = @subsetting_items.map { |item| item.start_with?(subsetting) ? nil : item }.compact else @subsetting_items = @subsetting_items.map { |item| item.eql?(subsetting) ? nil : item }.compact end end end end end puppetlabs-inifile-1.4.2/lib/puppet/util/ini_file/section.rb000644 000766 000024 00000006102 12571432054 024362 0ustar00bmjenstaff000000 000000 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 puppetlabs-inifile-1.4.2/lib/puppet/type/ini_setting.rb000644 000766 000024 00000003321 12571432054 023460 0ustar00bmjenstaff000000 000000 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.' munge do |value| if value =~ /(^\s|\s$)/ Puppet.warn("Settings should not have spaces in the value, we are going to strip the whitespace") end value.lstrip.rstrip end 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 puppetlabs-inifile-1.4.2/lib/puppet/type/ini_subsetting.rb000644 000766 000024 00000004027 12571432054 024176 0ustar00bmjenstaff000000 000000 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 newparam(:use_exact_match) do desc 'Set to true if your subsettings don\'t have values and you want to use exact matches to determine if the subsetting exists. See MODULES-2212' newvalues(:true, :false) defaultto(:false) end newproperty(:value) do desc 'The value of the subsetting to be defined.' end end puppetlabs-inifile-1.4.2/lib/puppet/provider/ini_setting/000755 000766 000024 00000000000 12571433714 024011 5ustar00bmjenstaff000000 000000 puppetlabs-inifile-1.4.2/lib/puppet/provider/ini_subsetting/000755 000766 000024 00000000000 12571433714 024523 5ustar00bmjenstaff000000 000000 puppetlabs-inifile-1.4.2/lib/puppet/provider/ini_subsetting/ruby.rb000644 000766 000024 00000003147 12571432054 026032 0ustar00bmjenstaff000000 000000 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, resource[:use_exact_match]) end def create setting_value.add_subsetting(subsetting, resource[:value], resource[:use_exact_match]) 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, resource[:use_exact_match]) 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], resource[:use_exact_match]) 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 puppetlabs-inifile-1.4.2/lib/puppet/provider/ini_setting/ruby.rb000644 000766 000024 00000006214 12571432054 025316 0ustar00bmjenstaff000000 000000 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 puppetlabs-inifile-1.4.2/lib/puppet/parser/functions/000755 000766 000024 00000000000 12571433714 023147 5ustar00bmjenstaff000000 000000 puppetlabs-inifile-1.4.2/lib/puppet/parser/functions/create_ini_settings.rb000644 000766 000024 00000004223 12571433667 027526 0ustar00bmjenstaff000000 000000 # # 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 : puppetlabs-inifile-1.4.2/examples/ini_setting.pp000644 000766 000024 00000001152 12571433667 022261 0ustar00bmjenstaff000000 000000 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'], } puppetlabs-inifile-1.4.2/examples/ini_subsetting.pp000644 000766 000024 00000001012 12571433667 022766 0ustar00bmjenstaff000000 000000 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', }