puppetlabs-inifile-2.2.10040755005276200011600000000000013265372213012225 5ustar00puppetlabs-inifile-2.2.1/CHANGELOG.md0100644005276200011600000002440513265372073014123 0ustar00# Changelog All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org). ## Supported Release [2.2.1] ### Summary This is a bug fix release for a problem with managing existing lines in Puppet > 5.4.0 ### Fixed - issue with ini_setting's :refreshonly parameter validation ([MODULES-6687](https://tickets.puppet.com/browse/MODULES-6687)) ## Supported Release [2.2.0] ### Summary This release uses the PDK convert functionality which in return makes the module PDK compliant. It also includes a roll up of maintenance changes. ### Added - PDK convert inifile ([MODULES-6453](https://tickets.puppet.com/browse/MODULES-6453)). - Modulesync updates. ### Fixed - Changes to address additional Rubocop failures. - Addressing puppet-lint doc warnings. ### Removed - `gem update bundler` command in .travis.yml due to ([MODULES-6339](https://tickets.puppet.com/browse/MODULES-6339)). ## Supported Release 2.1.1 ### Summary This release is in order to implement Rubocop within the module and includes a wide array of formatting changes throughout the code and the enabling of rubocop checks to be run against all pull requests against the module. ### Changed - Rubocop checks will now be run against any PRs made towards the module. - The module has undergone a substantial reformatting in order to comply with the designated standards. ## Supported Release 2.1.0 ### Summary This is a clean release prior to the implementation of rubocop within the module. ### Added - Several Modulesync updates have been made. - Indent Character can now be set. - Support for Debian 9 has been added. ### Removed - Support for Ubuntu 1004 and 1204 has been removed. - Support for SLES 10 SP4 has been removed. - Support for Debian 6 has been removed. - Support for Solaris 12 has been removed. - Support for Windows Server 2003 R2 has been removed. ## Supported Release 2.0.0 ### Summary This is a major release that includes a few bugfixes as well as some general module updates. **This release drops Puppet 3 support** ### Changed - Moved lower Puppet version requirement to 4.7.0, MODULES-4830 ### Fixed - Fix path validation on windows MODULES-4170 - Fix headings in README - Fix for mimicking commented settings MODULES-4932 - Fix for Backwards compatible ini_file.set_value MODULES-5172 ## Supported Release 1.6.0 ### Summary This release expands functionality around sub-settings and adds the `refreshonly` parameter so the user can specify whether a resource should or should not respond to a refresh event. ### Features - `refreshonly` decide whether or not a value should be updated as part of a refresh - `insert_type` choose where the sub-setting is placed in the final string - `subsetting_key_val_separator` specify a key/value separator for sub-settings ### Bugfixes - MODULES-3145 Cast values to strings before passing to provider ## Supported Release 1.5.0 ### Summary This release adds the long-awaited `show_diff` parameter for diffing the complete file on changes (or can also just show the md5 sums). ### Features - Added `show_diff` parameter to show diffs on changes. - Remove empty ini sections when the last line in the section is removed. ### Bugfixes - Workaround `create_ini_settings()` duplicate resources puppet bug PUP-4709 ## Supported Release 1.4.3 ###Summary Small release for support of newer PE versions. This increments the version of PE in the metadata.json file. ## 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) [2.2.0]:https://github.com/puppetlabs/puppetlabs-apt/compare/2.1.1...2.2.0 puppetlabs-inifile-2.2.1/CONTRIBUTING.md0100644005276200011600000002306013261374561014537 0ustar00# Contributing to Puppet modules So you want to contribute to a Puppet module: Great! Below are some instructions to get you started doing that very thing while setting expectations around code quality as well as a few tips for making the process as easy as possible. ### Table of Contents 1. [Getting Started](#getting-started) 1. [Commit Checklist](#commit-checklist) 1. [Submission](#submission) 1. [More about commits](#more-about-commits) 1. [Testing](#testing) - [Running Tests](#running-tests) - [Writing Tests](#writing-tests) 1. [Get Help](#get-help) ## Getting Started - Fork the module repository on GitHub and clone to your workspace - Make your changes! ## Commit Checklist ### The Basics - [x] my commit is a single logical unit of work - [x] I have checked for unnecessary whitespace with "git diff --check" - [x] my commit does not include commented out code or unneeded files ### The Content - [x] my commit includes tests for the bug I fixed or feature I added - [x] my commit includes appropriate documentation changes if it is introducing a new feature or changing existing functionality - [x] my code passes existing test suites ### The Commit Message - [x] the first line of my commit message includes: - [x] an issue number (if applicable), e.g. "(MODULES-xxxx) This is the first line" - [x] a short description (50 characters is the soft limit, excluding ticket number(s)) - [x] the body of my commit message: - [x] is meaningful - [x] uses the imperative, present tense: "change", not "changed" or "changes" - [x] includes motivation for the change, and contrasts its implementation with the previous behavior ## Submission ### Pre-requisites - Make sure you have a [GitHub account](https://github.com/join) - [Create a ticket](https://tickets.puppet.com/secure/CreateIssue!default.jspa), or [watch the ticket](https://tickets.puppet.com/browse/) you are patching for. ### Push and PR - Push your changes to your fork - [Open a Pull Request](https://help.github.com/articles/creating-a-pull-request-from-a-fork/) against the repository in the puppetlabs organization ## More about commits 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](https://help.github.com/articles/creating-a-pull-request-from-a-fork/). 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 JIRA issue. If there is a JIRA 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, and then use it to install all dependencies needed for this project in the project root by running ```shell % bundle install --path .bundle/gems 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 ``` ## Running Tests With all dependencies in place and up-to-date, run the tests: ### Unit Tests ```shell % bundle exec rake spec ``` This executes all the [rspec tests](http://rspec-puppet.com/) in the directories defined [here](https://github.com/puppetlabs/puppetlabs_spec_helper/blob/699d9fbca1d2489bff1736bb254bb7b7edb32c74/lib/puppetlabs_spec_helper/rake_tasks.rb#L17) and so on. rspec tests may have the same kind of dependencies as the module they are testing. Although the module defines these dependencies in its [metadata.json](./metadata.json), rspec tests define them in [.fixtures.yml](./fixtures.yml). ### Acceptance Tests Some Puppet modules also come with acceptance tests, which use [beaker][]. These tests spin up a virtual machine under [VirtualBox](https://www.virtualbox.org/), controlled with [Vagrant](http://www.vagrantup.com/), to simulate scripted test scenarios. In order to run these, you need both Virtualbox and Vagrant installed on your system. Run the tests 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 ### Unit Tests When writing unit tests for Puppet, [rspec-puppet][] is your best friend. It provides tons of helper methods for testing your manifests against a catalog (e.g. contain_file, contain_package, with_params, etc). It would be ridiculous to try and top rspec-puppet's [documentation][rspec-puppet_docs] but here's a tiny sample: Sample manifest: ```puppet file { "a test file": ensure => present, path => "/etc/sample", } ``` Sample test: ```ruby it 'does a thing' do expect(subject).to contain_file("a test file").with({:path => "/etc/sample"}) end ``` ### Acceptance Tests Writing acceptance tests for Puppet involves [beaker][] and its cousin [beaker-rspec][]. A common pattern for acceptance tests is to create a test manifest, apply it twice to check for idempotency or errors, then run expectations. ```ruby it 'does an end-to-end thing' do pp = <<-EOF file { 'a test file': ensure => present, path => "/etc/sample", content => "test string", } apply_manifest(pp, :catch_failures => true) apply_manifest(pp, :catch_changes => true) end describe file("/etc/sample") do it { is_expected.to contain "test string" } end ``` # If you have commit access to the repository Even if you have commit access to the repository, you 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 project developer that did not write the code to ensure that all changes go through a code review process.** The record of someone performing the merge is the record that they performed the code review. Again, this should be someone other than the author of the topic branch. # Get Help ### On the web * [Puppet help messageboard](http://puppet.com/community/get-help) * [Writing tests](https://docs.puppet.com/guides/module_guides/bgtm.html#step-three-module-testing) * [General GitHub documentation](http://help.github.com/) * [GitHub pull request documentation](http://help.github.com/send-pull-requests/) ### On chat * Slack (slack.puppet.com) #forge-modules, #puppet-dev, #windows, #voxpupuli * IRC (freenode) #puppet-dev, #voxpupuli [rspec-puppet]: http://rspec-puppet.com/ [rspec-puppet_docs]: http://rspec-puppet.com/documentation/ [beaker]: https://github.com/puppetlabs/beaker [beaker-rspec]: https://github.com/puppetlabs/beaker-rspec puppetlabs-inifile-2.2.1/Gemfile0100644005276200011600000001350413261374561013603 0ustar00source ENV['GEM_SOURCE'] || 'https://rubygems.org' def location_for(place_or_version, fake_version = nil) if place_or_version =~ %r{\A(git[:@][^#]*)#(.*)} [fake_version, { git: Regexp.last_match(1), branch: Regexp.last_match(2), require: false }].compact elsif place_or_version =~ %r{\Afile:\/\/(.*)} ['>= 0', { path: File.expand_path(Regexp.last_match(1)), require: false }] else [place_or_version, { require: false }] end end def gem_type(place_or_version) if place_or_version =~ %r{\Agit[:@]} :git elsif !place_or_version.nil? && place_or_version.start_with?('file:') :file else :gem end end ruby_version_segments = Gem::Version.new(RUBY_VERSION.dup).segments minor_version = ruby_version_segments[0..1].join('.') group :development do gem "fast_gettext", '1.1.0', require: false if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.1.0') gem "fast_gettext", require: false if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.1.0') gem "json_pure", '<= 2.0.1', require: false if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.0.0') gem "json", '= 1.8.1', require: false if Gem::Version.new(RUBY_VERSION.dup) == Gem::Version.new('2.1.9') gem "puppet-module-posix-default-r#{minor_version}", require: false, platforms: [:ruby] gem "puppet-module-posix-dev-r#{minor_version}", require: false, platforms: [:ruby] gem "puppet-module-win-default-r#{minor_version}", require: false, platforms: [:mswin, :mingw, :x64_mingw] gem "puppet-module-win-dev-r#{minor_version}", require: false, platforms: [:mswin, :mingw, :x64_mingw] gem "puppet-blacksmith", '~> 3.4', require: false end group :system_tests do gem "puppet-module-posix-system-r#{minor_version}", require: false, platforms: [:ruby] gem "puppet-module-win-system-r#{minor_version}", require: false, platforms: [:mswin, :mingw, :x64_mingw] gem "beaker", *location_for(ENV['BEAKER_VERSION'] || '~> 3.13') gem "beaker-abs", *location_for(ENV['BEAKER_ABS_VERSION'] || '~> 0.1') gem "beaker-pe", require: false gem "beaker-hostgenerator" gem "beaker-rspec" end puppet_version = ENV['PUPPET_GEM_VERSION'] puppet_type = gem_type(puppet_version) facter_version = ENV['FACTER_GEM_VERSION'] hiera_version = ENV['HIERA_GEM_VERSION'] def puppet_older_than?(version) puppet_version = ENV['PUPPET_GEM_VERSION'] !puppet_version.nil? && Gem::Version.correct?(puppet_version) && Gem::Requirement.new("< #{version}").satisfied_by?(Gem::Version.new(puppet_version.dup)) end gems = {} gems['puppet'] = location_for(puppet_version) # If facter or hiera versions have been specified via the environment # variables, use those versions. If not, and if the puppet version is < 3.5.0, # use known good versions of both for puppet < 3.5.0. if facter_version gems['facter'] = location_for(facter_version) elsif puppet_type == :gem && puppet_older_than?('3.5.0') gems['facter'] = ['>= 1.6.11', '<= 1.7.5', require: false] end if hiera_version gems['hiera'] = location_for(ENV['HIERA_GEM_VERSION']) elsif puppet_type == :gem && puppet_older_than?('3.5.0') gems['hiera'] = ['>= 1.0.0', '<= 1.3.0', require: false] end if Gem.win_platform? && (puppet_type != :gem || puppet_older_than?('3.5.0')) # For Puppet gems < 3.5.0 (tested as far back as 3.0.0) on Windows if puppet_type == :gem gems['ffi'] = ['1.9.0', require: false] gems['minitar'] = ['0.5.4', require: false] gems['win32-eventlog'] = ['0.5.3', '<= 0.6.5', require: false] gems['win32-process'] = ['0.6.5', '<= 0.7.5', require: false] gems['win32-security'] = ['~> 0.1.2', '<= 0.2.5', require: false] gems['win32-service'] = ['0.7.2', '<= 0.8.8', require: false] else gems['ffi'] = ['~> 1.9.0', require: false] gems['minitar'] = ['~> 0.5.4', require: false] gems['win32-eventlog'] = ['~> 0.5', '<= 0.6.5', require: false] gems['win32-process'] = ['~> 0.6', '<= 0.7.5', require: false] gems['win32-security'] = ['~> 0.1', '<= 0.2.5', require: false] gems['win32-service'] = ['~> 0.7', '<= 0.8.8', require: false] end gems['win32-dir'] = ['~> 0.3', '<= 0.4.9', require: false] if RUBY_VERSION.start_with?('1.') gems['win32console'] = ['1.3.2', require: false] # sys-admin was removed in Puppet 3.7.0 and doesn't compile under Ruby 2.x gems['sys-admin'] = ['1.5.6', require: false] end # Puppet < 3.7.0 requires these. # Puppet >= 3.5.0 gem includes these as requirements. # The following versions are tested to work with 3.0.0 <= puppet < 3.7.0. gems['win32-api'] = ['1.4.8', require: false] gems['win32-taskscheduler'] = ['0.2.2', require: false] gems['windows-api'] = ['0.4.3', require: false] gems['windows-pr'] = ['1.2.3', require: false] elsif Gem.win_platform? # If we're using a Puppet gem on Windows which handles its own win32-xxx gem # dependencies (>= 3.5.0), set the maximum versions (see PUP-6445). gems['win32-dir'] = ['<= 0.4.9', require: false] gems['win32-eventlog'] = ['<= 0.6.5', require: false] gems['win32-process'] = ['<= 0.7.5', require: false] gems['win32-security'] = ['<= 0.2.5', require: false] gems['win32-service'] = ['<= 0.8.8', require: false] end gems.each do |gem_name, gem_params| gem gem_name, *gem_params end # Evaluate Gemfile.local and ~/.gemfile if they exist extra_gemfiles = [ "#{__FILE__}.local", File.join(Dir.home, '.gemfile'), ] extra_gemfiles.each do |gemfile| if File.file?(gemfile) && File.readable?(gemfile) eval(File.read(gemfile), binding) end end # vim: syntax=ruby puppetlabs-inifile-2.2.1/LICENSE0100644005276200011600000002613613261374561013322 0ustar00 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 [yyyy] [name of copyright owner] 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-2.2.1/MAINTAINERS.md0100644005276200011600000000027713261374561014407 0ustar00## Maintenance Maintainers: - Puppet Forge Modules Team `forge-modules |at| puppet |dot| com` Tickets: https://tickets.puppet.com/browse/MODULES. Make sure to set component to `inifile`. puppetlabs-inifile-2.2.1/NOTICE0100644005276200011600000000124413261374561013212 0ustar00inifile puppet module Copyright (C) 2012-2016 Puppet Labs, Inc. Copyright (C) 2012 Chris Price Puppet Labs can be contacted at: info@puppetlabs.com 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-2.2.1/README.markdown0100644005276200011600000003745213265372073015021 0ustar00# 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) 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 is used to: * Support comments starting with either '#' or ';'. * Support either whitespace or no whitespace around '='. * Add any missing sections to the INI file. It does not manipulate your file any more than it needs to. In most cases, it doesn't affect the original whitespace, comments, or ordering. See the common usages below for examples. ### 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 ~~~ ### Use a non-standard indent character To use a non-standard indent character or string for added settings, set the `indent_char` and the `indent_width` parameters. The `indent_width` parameter controls how many `indent_char` appear in the indent. ~~~puppet ini_setting { 'procedure cache size': ensure => present, path => '/var/lib/ase/config/ASE-16_0/SYBASE.cfg', section => 'SQL Server Administration', setting => 'procedure cache size', value => '15000', indent_char => "\t", indent_width => 2, } ~~~ Results in: ~~~puppet [SQL Server Administration] procedure cache size = 15000 ~~~ ### Implement child providers You might want to create child providers that inherit the `ini_setting` provider for one of the following reasons: * To make a custom resource to manage an application that stores its settings in INI files, without recreating the code to manage the files themselves. * To [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 you can manage the settings in the `/etc/glance/glance-api.conf` file 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 the 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, use 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 All parameters are optional unless specified as required. ##### `ensure` Determines whether the specified setting should exist. Valid options: 'present' and 'absent'. Default value: 'present'. ##### `key_val_separator` Specifies a string to use between each setting name and value, for example, to determine whether the separator includes whitespace. Valid options: a string. Default value: ' = '. ##### `name` 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` 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. Default value: "". ##### `setting` *Required.* Designates a setting to manage within the specified INI file and section. Valid options: a string. ##### `show_diff` Prevents outputting actual values to the logfile. This is useful for the handling of passwords and other sensitive information. Possible values are: * `true`: This allows all values to be passed to logfiles. (default) * `false`: The values in the logfiles will be replaced with `[redacted sensitive information]`. * `md5`: The values in the logfiles will be replaced with their md5 hash. Global `show_diff` configuration takes priority over this one: [https://docs.puppetlabs.com/references/latest/configuration.html#showdiff]([https://docs.puppetlabs.com/references/latest/configuration.html#showdiff]. ). Default value: `true`. ##### `value` Supplies a value for the specified setting. Valid options: a string. Default value: `undef`. ##### `section_prefix` Designates the string to appear before the section's name. Default value: "[" ##### `section_suffix` Designates the string to appear after the section's name. Default value: "]". ##### `indent_char` Designates the character (or string) to indent newly created settings. This does not affect settings that already exist in the file, even if they change. Default value: " ". ##### `indent_width` Designates the number of `indent_char` with which to indent newly inserted settings. If this is not defined, the indentation is automatically computed from existing settings in the section, or if the section does not yet exist, no indent is made. This does not affect settings that already exist in the file, even if they change. ##### `refreshonly` A Boolean to indicate whether the value associated with the setting should be updated, if this resource is only part of a refresh event. Default value: `false`. For example, if we want a timestamp associated with the last time a setting's value was updated, we could do something like this: ~~~ ini_setting { 'foosetting': ensure => present, path => '/tmp/file.ini', section => 'foo', setting => 'foosetting', value => 'bar', notify => Ini_Setting['foosetting_timestamp'], } $now = strftime('%Y-%m-%d %H:%M:%S') ini_setting {'foosetting_timestamp': ensure => present, path => '/tmp/file.ini', section => 'foo', setting => 'foosetting_timestamp', value => $now, refreshonly => true, } ~~~ **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 All parameters are optional unless specified as required. ##### `ensure` Specifies whether the subsetting should be present. Valid options: 'present' and 'absent'. Default value: 'present'. ##### `key_val_separator` Specifies a string to use between setting name and value, for example, 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` The character used to quote the entire value of the setting. Valid options: '', '"' and "'". Default value: ''. ##### `section` Designates a section of the specified INI file containing the setting to manage. You can manage a global setting by putting it at the beginning of the file, before any named sections, and entering "". Valid options: a string. Default value: "". ##### `setting` *Required.* Designates a setting within the specified section containing the subsetting to manage. Valid options: a string. ##### `show_diff` Prevents outputting actual values to the logfile. This is useful for the handling of passwords and other sensitive information. Possible values are: * `true`: This allows all values to be passed to logfiles. (default) * `false`: The values in the logfiles will be replaced with `[redacted sensitive information]`. * `md5`: The values in the logfiles will be replaced with their md5 hash. Global show_diff configuraton takes priority over this one - [https://docs.puppetlabs.com/references/latest/configuration.html#showdiff]([https://docs.puppetlabs.com/references/latest/configuration.html#showdiff]. ). Default value: 'true'. ##### `subsetting` *Required.* Designates a subsetting to manage within the specified setting. Valid options: a string. ##### `subsetting_separator` Specifies a string to use between subsettings. Valid options: a string. Default value: " ". ##### `subsetting_key_val_separator` Specifies a string to use between the subsetting name and value (if there is a separator between the subsetting name and its value). Valid options: a string. Default value: empty string. ##### `use_exact_match` Whether to use partial or exact matching for subsetting. This should be set to `true` if the subsettings do not have values. Valid options: `true`, `false`. Default value: `false`. ##### `value` Supplies a value for the specified subsetting. Valid options: a string. Default value: `undef`. ##### `insert_type` Selects where a new subsetting item should be inserted. * *start* - insert at the beginning of the line. * *end* - insert at the end of the line (default). * *before* - insert before the specified element if possible. * *after* - insert after the specified element if possible. * *index* - insert at the specified index number. ##### `insert_value` The value for the insert type, if the value is required. ### 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.* Specifies a hash representing the `ini_setting` resources you want to create. ##### Second argument: `defaults` Accepts a hash to be used as the values for 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. Due to (PUP-4709) the create_ini_settings function will cause errors when attempting to create multiple ini_settings in one go when using Puppet 4.0.x or 4.1.x. If needed, the temporary fix for this can be found here: https://github.com/puppetlabs/puppetlabs-inifile/pull/196. ## 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-2.2.1/Rakefile0100644005276200011600000000017713261374561013757 0ustar00require 'puppetlabs_spec_helper/rake_tasks' require 'puppet-syntax/tasks/puppet-syntax' require 'puppet_blacksmith/rake_tasks' puppetlabs-inifile-2.2.1/appveyor.yml0100644005276200011600000000330013261374561014671 0ustar00version: 1.1.x.{build} skip_commits: message: /^\(?doc\)?.*/ clone_depth: 10 init: - SET - 'mkdir C:\ProgramData\PuppetLabs\code && exit 0' - 'mkdir C:\ProgramData\PuppetLabs\facter && exit 0' - 'mkdir C:\ProgramData\PuppetLabs\hiera && exit 0' - 'mkdir C:\ProgramData\PuppetLabs\puppet\var && exit 0' environment: PUPPET_GEM_VERSION: ~> 4.0 matrix: - RUBY_VERSION: 24-x64 CHECK: syntax lint - RUBY_VERSION: 24-x64 CHECK: metadata_lint - RUBY_VERSION: 24-x64 CHECK: rubocop - RUBY_VERSION: 24-x64 CHECK: spec - RUBY_VERSION: 21-x64 CHECK: spec - PUPPET_GEM_VERSION: ~> 5.0 RUBY_VERSION: 24-x64 CHECK: spec matrix: fast_finish: true install: - set PATH=C:\Ruby%RUBY_VERSION%\bin;%PATH% # Due to a bug in the version of OpenSSL shipped with Ruby 2.4.1 on Windows # (https://bugs.ruby-lang.org/issues/11033). Errors are ignored because the # mingw gem calls out to pacman to install OpenSSL which is already # installed, causing gem to raise a warning that powershell determines to be # a fatal error. - ps: | $ErrorActionPreference = "SilentlyContinue" if($env:RUBY_VERSION -eq "24-x64") { gem install openssl "~> 2.0.4" --no-rdoc --no-ri -- --with-openssl-dir=C:\msys64\mingw64 } $host.SetShouldExit(0) - bundle install --jobs 4 --retry 2 --without system_tests - type Gemfile.lock build: off test_script: - bundle exec puppet -V - ruby -v - gem -v - bundle -v - bundle exec rake %CHECK% notifications: - provider: Email to: - nobody@nowhere.com on_build_success: false on_build_failure: false on_build_status_changed: false puppetlabs-inifile-2.2.1/checksums.json0100644005276200011600000000743313265372213015170 0ustar00{ "CHANGELOG.md": "b8436c305a9c5f895347785070f09ea8", "CONTRIBUTING.md": "4d17f3c942e7c93d1577cc4438a231e4", "Gemfile": "47f2bb73e730d42a921e7bca4449f5aa", "LICENSE": "3b83ef96387f14655fc854ddc3c6bd57", "MAINTAINERS.md": "601b5502368255945a0ec51758d24d72", "NOTICE": "d8696846ced56eb64cd473c23a68bf64", "README.markdown": "a600817c9df0fcfb35cc1d4d040c3be4", "Rakefile": "df4172642435e770c27019d9d15d59bd", "appveyor.yml": "554f948d382f2d1762e275a186395cb3", "examples/ini_setting.pp": "9c8a9d2c453901cedb106cada253f1f6", "examples/ini_subsetting.pp": "16ef08c1534754b47120e58fa9e2f068", "lib/puppet/parser/functions/create_ini_settings.rb": "ca8352ebba5d87f3e78afcfc18dcc4ef", "lib/puppet/provider/ini_setting/ruby.rb": "ffc326166fb9148dd432354ebab4c3d1", "lib/puppet/provider/ini_subsetting/ruby.rb": "d7ffb252b4d81ecd417ec7d5380c32e7", "lib/puppet/type/ini_setting.rb": "587402234338cb19e341075b017a63b3", "lib/puppet/type/ini_subsetting.rb": "3c0c4a76d242c1030e96609fce75f981", "lib/puppet/util/external_iterator.rb": "aeeaae87574c2d2b895a186b3b03b67c", "lib/puppet/util/ini_file/section.rb": "28eecbff12038405b868ebc5763e87a6", "lib/puppet/util/ini_file.rb": "17eb6723872253fd68d49517396fa69a", "lib/puppet/util/setting_value.rb": "13ffa9f47a8aa6d0d26f9dfd4f717d49", "locales/config.yaml": "2689a5a8fc3c80d049cddc4197ea7b3a", "metadata.json": "1335d134b6501559c91ee42263d38cb1", "spec/acceptance/ini_setting_spec.rb": "4429f00781ccdc709bf3393f8c344e63", "spec/acceptance/ini_subsetting_spec.rb": "32f164bb7e210e074c2388a4fe7de1c4", "spec/acceptance/nodesets/centos-7-x64.yml": "a713f3abd3657f0ae2878829badd23cd", "spec/acceptance/nodesets/debian-8-x64.yml": "d2d2977900989f30086ad251a14a1f39", "spec/acceptance/nodesets/default.yml": "b42da5a1ea0c964567ba7495574b8808", "spec/acceptance/nodesets/docker/centos-7.yml": "8a3892807bdd62306ae4774f41ba11ae", "spec/acceptance/nodesets/docker/debian-8.yml": "ac8e871d1068c96de5e85a89daaec6df", "spec/acceptance/nodesets/docker/ubuntu-14.04.yml": "dc42ee922a96908d85b8f0f08203ce58", "spec/classes/create_ini_settings_test_spec.rb": "bc5d3eb29dd05af9380e0e7082514e73", "spec/classes/create_multiple_ini_settings_spec.rb": "0b71592f15f249c95d70c8be6ffb11da", "spec/classes/inherit_test1_spec.rb": "a19362ce956087ba0abdbae7a28b99d6", "spec/fixtures/create_ini_settings_test/manifests/init.pp": "24dfde4e5e727c491d7388445369ca3d", "spec/fixtures/create_multiple_ini_settings/manifests/init.pp": "14be9a3873627bafe4d4cb022b395715", "spec/fixtures/inherit_ini_setting/lib/puppet/provider/inherit_ini_setting/ini_setting.rb": "16cdab9b4d6cfa8f4013ed7ea6420c3c", "spec/fixtures/inherit_ini_setting/lib/puppet/type/inherit_ini_setting.rb": "ec08c7a0a841f929c5b698d468b052be", "spec/fixtures/inherit_test1/manifests/init.pp": "55bb7494f2a13139e1f610c234222d84", "spec/functions/create_ini_settings_spec.rb": "f88c156503aa026e843ce08b81a72bc1", "spec/spec_helper.rb": "182136c8450f0af179fa0705ce971587", "spec/spec_helper_acceptance.rb": "040556dac7a8802e52c34997bfd955a0", "spec/spec_helper_local.rb": "76b869c1f6c144f1defea8239c53d1aa", "spec/unit/puppet/provider/ini_setting/inheritance_spec.rb": "11928630136a29199da48948fede2f1e", "spec/unit/puppet/provider/ini_setting/ruby_spec.rb": "af8d6f90c4ed97874a5651ad60898f7d", "spec/unit/puppet/provider/ini_subsetting/ruby_spec.rb": "ded5c4b44044aefef2ec344ce7fcab41", "spec/unit/puppet/type/ini_setting_spec.rb": "644097704f8418d8d32b81feb57c55a4", "spec/unit/puppet/type/ini_subetting_spec.rb": "f1f166b14cc352563225197d645dc2ef", "spec/unit/puppet/util/external_iterator_spec.rb": "da28f50cb1870faa1e23a96ae7ca03e0", "spec/unit/puppet/util/ini_file_spec.rb": "c0392d3cf0af0837391f072794fe6467", "spec/unit/puppet/util/setting_value_spec.rb": "b92633de5968905743dd7fa964162c2a" }puppetlabs-inifile-2.2.1/examples0040755005276200011600000000000013265372213014043 5ustar00puppetlabs-inifile-2.2.1/examples/ini_setting.pp0100644005276200011600000000115213261374561016777 0ustar00ini_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-2.2.1/examples/ini_subsetting.pp0100644005276200011600000000200513261374561017507 0ustar00ini_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', } ini_subsetting { 'sample subsetting3': ensure => 'present', section => '', key_val_separator => '=', subsetting_key_val_separator => ':', path => '/etc/default/pe-puppetdb', setting => 'JAVA_ARGS', subsetting => '-XX', value => '+HeapDumpOnOutOfMemoryError', insert_type => 'after', insert_value => '-Xmx', } puppetlabs-inifile-2.2.1/lib0040755005276200011600000000000013265372213012773 5ustar00puppetlabs-inifile-2.2.1/lib/puppet0040755005276200011600000000000013265372213014310 5ustar00puppetlabs-inifile-2.2.1/lib/puppet/parser0040755005276200011600000000000013265372213015604 5ustar00puppetlabs-inifile-2.2.1/lib/puppet/parser/functions0040755005276200011600000000000013265372213017614 5ustar00puppetlabs-inifile-2.2.1/lib/puppet/parser/functions/create_ini_settings.rb0100644005276200011600000000511513261374561024245 0ustar00# # 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{'/tmp/foo.ini [section1] setting1': ensure => present, section => 'section1', setting => 'setting1', value => 'val1', path => '/tmp/foo.ini', } ini_setting{'/tmp/foo.ini [section2] setting2': ensure => present, section => 'section2', setting => 'setting2', value => 'val2', path => '/tmp/foo.ini', } ini_setting{'/tmp/foo.ini [section2] setting3': ensure => absent, section => 'section2', setting => 'setting3', path => '/tmp/foo.ini', } EOS ) do |arguments| unless arguments.size.between?(1, 2) raise(Puppet::ParseError, 'create_ini_settings(): Wrong number of arguments ' \ "given (#{arguments.size} for 1 or 2)") end 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.each_with_object({}) do |section, res| unless settings[section].is_a?(Hash) raise(Puppet::ParseError, "create_ini_settings(): Section #{section} must contain a Hash") end path = defaults.merge(settings)['path'] raise Puppet::ParseError, 'create_ini_settings(): must pass the path parameter to the Ini_setting resource!' unless path settings[section].each do |setting, value| res["#{path} [#{section}] #{setting}"] = { 'ensure' => 'present', 'section' => section, 'setting' => setting, }.merge(if value.is_a?(Hash) value else { 'value' => value } end) end 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-2.2.1/lib/puppet/provider0040755005276200011600000000000013265372213016142 5ustar00puppetlabs-inifile-2.2.1/lib/puppet/provider/ini_setting0040755005276200011600000000000013265372213020456 5ustar00puppetlabs-inifile-2.2.1/lib/puppet/provider/ini_setting/ruby.rb0100644005276200011600000000661713261374561022056 0ustar00require 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. raise(Puppet::Error, 'Ini_settings only support collecting instances when a file path is hard coded') unless 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 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, separator, 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, separator, 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 def indent_char if resource.class.validattr?(:indent_char) resource[:indent_char] || ' ' else ' ' end end def indent_width if resource.class.validattr?(:indent_width) resource[:indent_width] || nil else nil end end private def ini_file @ini_file ||= Puppet::Util::IniFile.new(file_path, separator, section_prefix, section_suffix, indent_char, indent_width) end end puppetlabs-inifile-2.2.1/lib/puppet/provider/ini_subsetting0040755005276200011600000000000013265372213021170 5ustar00puppetlabs-inifile-2.2.1/lib/puppet/provider/ini_subsetting/ruby.rb0100644005276200011600000000366613261374561022571 0ustar00require 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], resource[:insert_type], resource[:insert_value] ) ini_file.set_value(section, setting, key_val_separator, 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, key_val_separator, 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, value, resource[:use_exact_match], resource[:insert_type], resource[:insert_value] ) ini_file.set_value(section, setting, key_val_separator, 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 key_val_separator resource[:key_val_separator] || '=' end def subsetting_key_val_separator resource[:subsetting_key_val_separator] || '' end def quote_char resource[:quote_char] end private def ini_file @ini_file ||= Puppet::Util::IniFile.new(file_path, key_val_separator) end def setting_value @setting_value ||= Puppet::Util::SettingValue.new( ini_file.get_value(section, setting), subsetting_separator, quote_char, subsetting_key_val_separator ) end end puppetlabs-inifile-2.2.1/lib/puppet/type0040755005276200011600000000000013265372213015271 5ustar00puppetlabs-inifile-2.2.1/lib/puppet/type/ini_setting.rb0100644005276200011600000000670513265372073020222 0ustar00require 'digest/md5' Puppet::Type.newtype(:ini_setting) do ensurable do defaultvalues defaultto :present end def munge_boolean_md5(value) case value when true, :true, 'true', :yes, 'yes' :true when false, :false, 'false', :no, 'no' :false when :md5, 'md5' :md5 else raise('expected a boolean value or :md5') end 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 =~ %r{(^\s|\s$)} Puppet.warn('Settings should not have spaces in the value, we are going to strip the whitespace') end value.strip end end newparam(:path) do desc 'The ini file Puppet will ensure contains the specified setting.' validate do |value| unless Puppet::Util.absolute_path?(value) raise(Puppet::Error, "File paths must be fully qualified, not '#{value}'") end end end newparam(:show_diff) do desc 'Whether to display differences when the setting changes.' defaultto :true newvalues(:true, :md5, :false) munge do |value| @resource.munge_boolean_md5(value) 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.' munge do |value| value.to_s end def should_to_s(newvalue) if @resource[:show_diff] == :true && Puppet[:show_diff] newvalue elsif @resource[:show_diff] == :md5 && Puppet[:show_diff] '{md5}' + Digest::MD5.hexdigest(newvalue.to_s) else '[redacted sensitive information]' end end def is_to_s(value) # rubocop:disable Style/PredicateName : Changing breaks the code (./.bundle/gems/gems/puppet-5.3.3-universal-darwin/lib/puppet/parameter.rb:525:in `to_s') should_to_s(value) end def insync?(current) if @resource[:refreshonly] true else current == should end end 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 newparam(:indent_char) do desc 'The character to indent new settings with.' \ 'Defaults to \' \'.' defaultto(' ') end newparam(:indent_width) do desc 'The number of indent_chars to use to indent a new setting.' \ 'Defaults to undef (autodetect).' end newparam(:refreshonly, boolean: true, parent: Puppet::Parameter::Boolean) do desc 'A flag indicating whether or not the ini_setting should be updated ' \ 'only when called as part of a refresh event' defaultto false end def refresh # update the value in the provider, which will save the value to the ini file provider.value = self[:value] if self[:refreshonly] end end puppetlabs-inifile-2.2.1/lib/puppet/type/ini_subsetting.rb0100644005276200011600000000743113261374561020731 0ustar00require 'digest/md5' Puppet::Type.newtype(:ini_subsetting) do ensurable do defaultvalues defaultto :present end def munge_boolean_md5(value) case value when true, :true, 'true', :yes, 'yes' :true when false, :false, 'false', :no, 'no' :false when :md5, 'md5' :md5 else raise('expected a boolean value or :md5') end 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(:subsetting_key_val_separator) do desc 'The separator string between the subsetting name and its value. Defaults to the empty string.' defaultto('') end newparam(:path) do desc 'The ini file Puppet will ensure contains the specified setting.' validate do |value| unless (Puppet.features.posix? && value =~ %r{^\/}) || (Puppet.features.microsoft_windows? && (value =~ %r{^.:\/} || value =~ %r{^\/\/[^\/]+\/[^\/]+})) raise(Puppet::Error, "File paths must be fully qualified, not '#{value}'") end end end newparam(:show_diff) do desc 'Whether to display differences when the setting changes.' defaultto :true newvalues(:true, :md5, :false) munge do |value| @resource.munge_boolean_md5(value) 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 =~ %r{^["']?$} 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.' def should_to_s(newvalue) if @resource[:show_diff] == :true && Puppet[:show_diff] newvalue elsif @resource[:show_diff] == :md5 && Puppet[:show_diff] '{md5}' + Digest::MD5.hexdigest(newvalue.to_s) else '[redacted sensitive information]' end end def is_to_s(value) # rubocop:disable Style/PredicateName : Changing breaks the code (./.bundle/gems/gems/puppet-5.3.3-universal-darwin/lib/puppet/parameter.rb:525:in `to_s') should_to_s(value) end end newparam(:insert_type) do desc <<-eof Where the new subsetting item should be inserted? * :start - insert at the beginning of the line. * :end - insert at the end of the line (default). * :before - insert before the specified element if possible. * :after - insert after the specified element if possible. * :index - insert at the specified index number. eof newvalues(:start, :end, :before, :after, :index) defaultto(:end) end newparam(:insert_value) do desc 'The value for the insert types which require one.' end end puppetlabs-inifile-2.2.1/lib/puppet/util0040755005276200011600000000000013265372213015265 5ustar00puppetlabs-inifile-2.2.1/lib/puppet/util/external_iterator.rb0100644005276200011600000000065513261374561021433 0ustar00module Puppet::Util # # external_iterator.rb # class ExternalIterator def initialize(coll) @coll = coll @cur_index = -1 end def next @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 puppetlabs-inifile-2.2.1/lib/puppet/util/ini_file0040755005276200011600000000000013265372213017043 5ustar00puppetlabs-inifile-2.2.1/lib/puppet/util/ini_file/section.rb0100644005276200011600000000563113261374561021121 0ustar00class Puppet::Util::IniFile # # section.rb # 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 global? @name == '' end def 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 existing_setting?(setting_name) @existing_settings.key?(setting_name) end def empty? start_line == end_line end def update_existing_setting(setting_name, value) @existing_settings[setting_name] = value end def remove_existing_setting(setting_name) @end_line -= 1 if @existing_settings.delete(setting_name) && @end_line 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 @end_line += 1 if @end_line 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 @start_line -= 1 if @start_line @end_line -= 1 if @end_line 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 @start_line += 1 if @start_line @end_line += 1 if @end_line end end end puppetlabs-inifile-2.2.1/lib/puppet/util/ini_file.rb0100644005276200011600000002706613261374561017463 0ustar00require File.expand_path('../external_iterator', __FILE__) require File.expand_path('../ini_file/section', __FILE__) module Puppet::Util # # ini_file.rb # class IniFile def initialize(path, key_val_separator = ' = ', section_prefix = '[', section_suffix = ']', indent_char = ' ', indent_width = nil) k_v_s = (key_val_separator =~ %r{^\s+$}) ? ' ' : key_val_separator.strip @section_prefix = section_prefix @section_suffix = section_suffix @indent_char = indent_char @indent_width = indent_width ? indent_width.to_i : nil @section_regex = section_regex @setting_regex = %r{^(\s*)([^#;\s]|[^#;\s].*?[^\s#{k_v_s}])(\s*#{k_v_s}[ \t]*)(.*)\s*$} @commented_setting_regex = %r{^(\s*)[#;]+(\s*)(.*?[^\s#{k_v_s}])(\s*#{k_v_s}[ \t]*)(.*)\s*$} @path = path @key_val_separator = key_val_separator @section_names = [] @sections_hash = {} parse_file if File.file?(@path) 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{#{r_string}} end attr_reader :section_names def get_settings(section_name) section = @sections_hash[section_name] section.setting_names.each_with_object({}) do |setting, result| result[setting] = section.get_value(setting) end end def get_value(section_name, setting) @sections_hash[section_name].get_value(setting) if @sections_hash.key?(section_name) end def set_value(*args) # rubocop:disable Style/AccessorMethodName : Recomended alternative is a common value name case args.size when 3 # Backwards compatible set_value function, See MODULES-5172 (section_name, setting, value) = args when 4 (section_name, setting, separator, value) = args end complete_setting = { setting: setting, separator: separator, value: value, } unless @sections_hash.key?(section_name) add_section(Section.new(section_name, nil, nil, nil, nil)) end section = @sections_hash[section_name] if section.existing_setting?(setting) update_line(section, setting, value) section.update_existing_setting(setting, value) elsif 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(find_commented_setting(section, setting), section, complete_setting) # 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] return unless section.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 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.new_section? && !section.global? fh.puts("\n#{@section_prefix}#{section.name}#{@section_suffix}") end unless section.new_section? # don't add empty sections if section.empty? && !section.global? next end # 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 =~ %r{^\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("#{@indent_char * (@indent_width || section.indentation || 0)}#{key}#{@key_val_separator}#{value}") end if !whitespace_buffer.empty? flush_buffer_to_file(whitespace_buffer, fh) elsif section.new_section? && !section.additional_settings.empty? && (index < @section_names.length - 1) # 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? && fh.puts('') 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 loop do line, line_num = line_iter.peek return Section.new(name, start_line, end_line_num, settings, min_indentation) if line_num.nil? || @section_regex.match(line) if (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| next unless (match = @setting_regex.match(lines[line_num])) if match[2] == setting lines[line_num] = "#{match[1]}#{match[2]}#{match[3]}#{value}" end end end def remove_line(section, setting) (section.start_line..section.end_line).each do |line_num| next unless (match = @setting_regex.match(lines[line_num])) if match[2] == setting lines.delete_at(line_num) 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) # rubocop:disable Lint/IneffectiveAccessModifier : Attempting to change breaks tests # 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.new_section? (section.start_line..section.end_line).each do |line_num| next unless (match = @commented_setting_regex.match(lines[line_num])) if match[3] == setting return { match: match, line_num: line_num } 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, complete_setting) line_num = result[:line_num] s = complete_setting lines.insert(line_num + 1, "#{@indent_char * (@indent_width || section.indentation || 0)}#{s[:setting]}#{s[:separator]}#{s[: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) return if buffer.empty? buffer.each { |l| fh.puts(l) } buffer.clear end end end puppetlabs-inifile-2.2.1/lib/puppet/util/setting_value.rb0100644005276200011600000001657013261374561020554 0ustar00module Puppet::Util # This class can work with a list of subsettings inside # an ini file setting string to add, remove, extract and set their values. class SettingValue # The constructor method # @param setting_value [String] The initial setting value # @param subsetting_separator [String] The character is used to separate # subsettings in the setting_value string. # @param default_quote_char [String] Quote the setting string with this character. def initialize(setting_value, subsetting_separator = ' ', default_quote_char = '', key_val_separator = '') @setting_value = setting_value @subsetting_separator = subsetting_separator @quote_char = default_quote_char @key_val_separator = key_val_separator @subsetting_items = [] return unless @setting_value unquoted, quote_char = unquote_setting_value(setting_value) @quote_char = quote_char unless quote_char.empty? # an item can contain escaped separator @subsetting_items = unquoted.scan(Regexp.new("(?:(?:[^\\#{@subsetting_separator}]|\\.)+)")) @subsetting_items.map! { |item| item.strip } end # If the setting value is quoted, the quotes are # removed and the unquoted string and the quoting # character are returned. # @param setting_value [String] The input value # @return [Array] The unquoted string and the quoting character def unquote_setting_value(setting_value) quote_char = '' if setting_value.start_with?('"') && setting_value.end_with?('"') quote_char = '"' elsif setting_value.start_with?("'") && setting_value.end_with?("'") quote_char = "'" end unquoted = if quote_char != '' setting_value[1, setting_value.length - 2] else setting_value end [unquoted, quote_char] end # Get the resulting setting value by joining all the # subsettings, separator and quote characters. # @return [String] def get_value # rubocop:disable Style/AccessorMethodName : Unable to alter without breaking code value = @subsetting_items.join @subsetting_separator @quote_char + value + @quote_char end # Get the value of the given subsetting item. # If the exact match is used the value will be true # if the item is found. # @param subsetting [String] The name of the subsetting to add. # @param use_exact_match [:true,:false] Should the full name match be used? # @return [nil,true,String] def get_subsetting_value(subsetting, use_exact_match = :false) index = find_subsetting(subsetting, use_exact_match) # the item is not found in the list return nil unless index # the exact match is set and the item is found, the value should be true return true if use_exact_match == :true item = @subsetting_items[index] item[(subsetting.length + @key_val_separator.length)..-1] end # Add a new subsetting item to the list of existing items # if such item is not already there. # @param subsetting [String] The name of the subsetting to add. # @param subsetting_value [String] The value of the subsetting. # It will be appended to the name. # @param use_exact_match [:true,:false] Should the full name match be used? # @param [Symbol] insert_type # @param [String,Integer] insert_value # @return [Array] The resulting subsettings list. def add_subsetting(subsetting, subsetting_value, use_exact_match = :false, insert_type = :end, insert_value = nil) index = find_subsetting(subsetting, use_exact_match) # update the existing values if the subsetting is found in the list return update_subsetting(subsetting, subsetting_value, use_exact_match) if index new_item = item_value(subsetting, subsetting_value) case insert_type when :start @subsetting_items.unshift(new_item) when :end @subsetting_items.push(new_item) when :before before_index = find_subsetting(insert_value, use_exact_match) if before_index @subsetting_items.insert(before_index, new_item) else @subsetting_items.push(new_item) end when :after after_index = find_subsetting(insert_value, use_exact_match) if after_index @subsetting_items.insert(after_index + 1, new_item) else @subsetting_items.push(new_item) end when :index before_index = insert_value.to_i before_index = @subsetting_items.length if before_index > @subsetting_items.length @subsetting_items.insert(before_index, new_item) else @subsetting_items.push(new_item) end @subsetting_items end # Update all matching items in the settings list to the new values. # @param subsetting [String] The name of the subsetting to add. # @param subsetting_value [String] The value of the subsetting. # @param use_exact_match [:true,:false] Should the full name match be used? # @return [Array] The resulting subsettings list. def update_subsetting(subsetting, subsetting_value, use_exact_match = :false) new_item = item_value(subsetting, subsetting_value) @subsetting_items.map! do |item| if match_subsetting?(item, subsetting, use_exact_match) new_item else item end end end # Find the first subsetting item matching the given name, # or, if the exact match is set, equal to the given name # and return its array index value. Returns nil if not found. # @param subsetting [String] The name of the subsetting to search. # @param use_exact_match [:true,:false] Look for the full string match? # @return [Integer, nil] def find_subsetting(subsetting, use_exact_match = :false) @subsetting_items.index do |item| match_subsetting?(item, subsetting, use_exact_match) end end # Check if the subsetting item matches the given name. # If the exact match is set the entire item is matched, # and only the item name and separator string if not. # @param item [String] The item value to check against the subsetting name. # @param subsetting [String] The subsetting name. # @param use_exact_match [:true,:false] Look for the full string match? # @return [true,false] def match_subsetting?(item, subsetting, use_exact_match = :false) if use_exact_match == :true item.eql?(subsetting) else item.start_with?(subsetting + @key_val_separator) end end # Remove all the subsetting items that match # the given subsetting name. # @param subsetting [String] The subsetting name to remove. # @param use_exact_match [:true,:false] Look for the full string match? # @return [Array] The resulting subsettings list. def remove_subsetting(subsetting, use_exact_match = :false) @subsetting_items.delete_if do |item| match_subsetting?(item, subsetting, use_exact_match) end end # The actual value of the subsetting item. # It's built from the subsetting name, its value and the separator # string if present. # @param subsetting [String] The subsetting name # @param subsetting_value [String] The value of the subsetting # @return [String] def item_value(subsetting, subsetting_value) (subsetting || '') + (@key_val_separator || '') + (subsetting_value || '') end end end puppetlabs-inifile-2.2.1/locales0040755005276200011600000000000013265372213013647 5ustar00puppetlabs-inifile-2.2.1/locales/config.yaml0100644005276200011600000000204613261374561016062 0ustar00--- # This is the project-specific configuration file for setting up # fast_gettext for your project. gettext: # This is used for the name of the .pot and .po files; they will be # called .pot? project_name: puppetlabs-inifile # This is used in comments in the .pot and .po files to indicate what # project the files belong to and should bea little more desctiptive than # package_name: puppetlabs-inifile # The locale that the default messages in the .pot file are in default_locale: en # The email used for sending bug reports. bugs_address: docs@puppet.com # The holder of the copyright. copyright_holder: Puppet, Inc. # This determines which comments in code should be eligible for translation. # Any comments that start with this string will be externalized. (Leave # empty to include all.) comments_tag: TRANSLATOR # Patterns for +Dir.glob+ used to find all files that might contain # translatable content, relative to the project root directory source_files: - './lib/**/*.rb' puppetlabs-inifile-2.2.1/metadata.json0100644005276200011600000000371213265372213014757 0ustar00{ "name": "puppetlabs-inifile", "version": "2.2.1", "author": "Puppet Labs", "summary": "Resource types for managing settings in INI files", "license": "Apache-2.0", "source": "https://github.com/puppetlabs/puppetlabs-inifile", "project_page": "https://github.com/puppetlabs/puppetlabs-inifile", "issues_url": "https://tickets.puppetlabs.com/browse/MODULES", "dependencies": [ ], "data_provider": null, "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": [ "11 SP1", "12" ] }, { "operatingsystem": "Debian", "operatingsystemrelease": [ "7", "8", "9" ] }, { "operatingsystem": "Ubuntu", "operatingsystemrelease": [ "14.04", "16.04" ] }, { "operatingsystem": "Solaris", "operatingsystemrelease": [ "10", "11" ] }, { "operatingsystem": "Windows", "operatingsystemrelease": [ "Server 2008 R2", "Server 2012", "Server 2012 R2" ] }, { "operatingsystem": "AIX", "operatingsystemrelease": [ "5.3", "6.1", "7.1" ] } ], "requirements": [ { "name": "puppet", "version_requirement": ">= 4.7.0 < 6.0.0" } ], "template-url": "file:///opt/puppetlabs/pdk/share/cache/pdk-templates.git", "template-ref": "1.3.2-0-g07678c8" } puppetlabs-inifile-2.2.1/spec0040755005276200011600000000000013265372213013157 5ustar00puppetlabs-inifile-2.2.1/spec/acceptance0040755005276200011600000000000013265372213015245 5ustar00puppetlabs-inifile-2.2.1/spec/acceptance/ini_setting_spec.rb0100644005276200011600000002355013261374561021205 0ustar00require '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 { is_expected.to be_file } describe '#content' do subject { super().content } it { is_expected.to match content } end 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 { is_expected.not_to be_file } end end context 'ensure parameter => 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, %r{four = five\n\n\[one\]\ntwo = three} end context 'ensure parameter => 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, %r{four = five\n\n\[one\]\ntwo = three} end context 'ensure parameter => 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 { is_expected.to be_file } describe '#content' do subject { super().content } it { is_expected.to match %r{four = five} } it { is_expected.not_to match %r{\[one\]} } it { is_expected.not_to match %r{two = three} } end end end context 'ensure parameter => 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 { is_expected.to be_file } describe '#content' do subject { super().content } it { is_expected.not_to match %r{four = five} } it { is_expected.to match %r{\[one\]} } it { is_expected.to match %r{two = three} } end end end describe 'section, setting, value parameters' do { "section => 'test', setting => 'foo', value => 'bar'," => %r{\[test\]\nfoo = bar}, "section => 'more', setting => 'baz', value => 'quux'," => %r{\[more\]\nbaz = quux}, "section => '', setting => 'top', value => 'level'," => %r{top = level}, "section => 'z', setting => 'sp aces', value => 'foo bar'," => %r{\[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'," => %r{setting is a required.+value is a required}, "setting => 'foo', value => 'bar'," => %r{section is a required}, "section => 'test', setting => 'foo'," => %r{value is a required}, "section => 'test', value => 'bar'," => %r{setting is a required}, "value => 'bar'," => %r{section is a required.+setting is a required}, "setting => 'foo'," => %r{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, %r{\[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, %r{must be fully qualified} end end describe 'key_val_separator parameter' do { '' => %r{two = three}, "key_val_separator => '='," => %r{two=three}, "key_val_separator => ' = '," => %r{two = three}, "key_val_separator => ' '," => %r{two three}, "key_val_separator => ' '," => %r{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 describe 'show_diff parameter and logging:' do [{ value: 'initial_value', matcher: 'created', show_diff: true }, { value: 'public_value', matcher: %r{initial_value.*public_value}, show_diff: true }, { value: 'secret_value', matcher: %r{redacted sensitive information.*redacted sensitive information}, show_diff: false }, { value: 'md5_value', matcher: %r{\{md5\}881671aa2bbc680bc530c4353125052b.*\{md5\}ed0903a7fa5de7886ca1a7a9ad06cf51}, show_diff: :md5 }].each do |i| pp = <<-EOS ini_setting { 'test_show_diff': ensure => present, section => 'test', setting => 'something', value => '#{i[:value]}', path => "#{tmpdir}/test_show_diff.ini", show_diff => #{i[:show_diff]} } EOS context "show_diff => #{i[:show_diff]}" do config = { 'main' => { 'show_diff' => true } } configure_puppet_on(default, config) res = apply_manifest(pp, expect_changes: true) it 'applies manifest and expects changed value to be logged in proper form' do expect(res.stdout).to match(i[:matcher]) end it 'applies manifest and expects changed value to be logged in proper form #optional test' do expect(res.stdout).not_to match(i[:value]) unless i[:show_diff] == true end end end end end puppetlabs-inifile-2.2.1/spec/acceptance/ini_subsetting_spec.rb0100644005276200011600000002470013261374561021715 0ustar00require '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 { is_expected.to be_file } describe '#content' do subject { super().content } it { is_expected.to match content } end 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 { is_expected.not_to be_file } end end describe 'ensure, section, setting, subsetting, & value parameters => 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 { is_expected.to be_file } describe '#content' do subject { super().content } it { is_expected.to match %r{\[one\]\nkey = alphabet betatrons} } end end end describe '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 { is_expected.to be_file } describe '#content' do subject { super().content } it { is_expected.to match %r{\[one\]} } it { is_expected.to match %r{key = betatrons} } it { is_expected.not_to match %r{alphabet} } end end end describe 'subsetting_separator' do { '' => %r{two = twinethree foobar}, "subsetting_separator => ','," => %r{two = twinethree,foobar}, "subsetting_separator => ' '," => %r{two = twinethree foobar}, "subsetting_separator => ' == '," => %r{two = twinethree == foobar}, "subsetting_separator => '='," => %r{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 'subsetting_key_val_separator' do { '' => %r{two = twinethree foobar}, "subsetting_key_val_separator => ':'," => %r{two = twine:three foo:bar}, "subsetting_key_val_separator => '-'," => %r{two = twine-three foo-bar}, }.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_key_val_separator.ini", before => Ini_subsetting['foobar'], #{parameter} } ini_subsetting { "foobar": ensure => 'present', section => 'one', setting => 'two', subsetting => 'foo', value => 'bar', path => "#{tmpdir}/subsetting_key_val_separator.ini", #{parameter} } EOS it_behaves_like 'has_content', "#{tmpdir}/subsetting_key_val_separator.ini", pp, content end end end describe 'quote_char' do { ['-Xmx'] => %r{args=""}, ['-Xmx', '256m'] => %r{args=-Xmx256m}, ['-Xmx', '512m'] => %r{args="-Xmx512m"}, ['-Xms', '256m'] => %r{args="-Xmx256m -Xms256m"}, }.each do |parameter, content| context %(with '#{parameter.first}' #{(parameter.length > 1) ? '=> \'' << parameter[1] << '\'' : 'absent'} makes '#{content}') do path = File.join(tmpdir, 'ini_subsetting.ini') before :all do shell(%(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 { is_expected.to be_file } describe '#content' do subject { super().content } it { is_expected.to match content } end end end end end describe 'show_diff parameter and logging:' do [{ value: 'initial_value', matcher: 'created', show_diff: true }, { value: 'public_value', matcher: %r{initial_value.*public_value}, show_diff: true }, { value: 'secret_value', matcher: %r{redacted sensitive information.*redacted sensitive information}, show_diff: false }, { value: 'md5_value', matcher: %r{\{md5\}881671aa2bbc680bc530c4353125052b.*\{md5\}ed0903a7fa5de7886ca1a7a9ad06cf51}, show_diff: :md5 }].each do |i| context "show_diff => #{i[:show_diff]}" do pp = <<-EOS ini_subsetting { 'test_show_diff': ensure => present, section => 'test', setting => 'something', subsetting => 'xxx', value => '#{i[:value]}', path => "#{tmpdir}/test_show_diff.ini", show_diff => #{i[:show_diff]} } EOS config = { 'main' => { 'show_diff' => true } } configure_puppet_on(default, config) res = apply_manifest(pp, expect_changes: true) it 'applies manifest and expects changed value to be logged in proper form' do expect(res.stdout).to match(i[:matcher]) end it 'applies manifest and expects changed value to be logged in proper form #optional test' do expect(res.stdout).not_to match(i[:value]) unless i[:show_diff] == true end end end end describe 'insert types:' do [ { insert_type: :start, content: %r{d a b c}, }, { insert_type: :end, content: %r{a b c d}, }, { insert_type: :before, insert_value: 'c', content: %r{a b d c}, }, { insert_type: :after, insert_value: 'a', content: %r{a d b c}, }, { insert_type: :index, insert_value: 2, content: %r{a b d c}, }, ].each do |params| context "with '#{params[:insert_type]}' makes '#{params[:content]}'" do pp = <<-EOS ini_subsetting { "a": ensure => present, section => 'one', setting => 'two', subsetting => 'a', path => "#{tmpdir}/insert_types.ini", } -> ini_subsetting { "b": ensure => present, section => 'one', setting => 'two', subsetting => 'b', path => "#{tmpdir}/insert_types.ini", } -> ini_subsetting { "c": ensure => present, section => 'one', setting => 'two', subsetting => 'c', path => "#{tmpdir}/insert_types.ini", } -> ini_subsetting { "insert makes #{params[:content]}": ensure => present, section => 'one', setting => 'two', subsetting => 'd', path => "#{tmpdir}/insert_types.ini", insert_type => '#{params[:insert_type]}', insert_value => '#{params[:insert_value]}', } EOS it_behaves_like 'has_content', "#{tmpdir}/insert_types.ini", pp, params[:content] end end end end puppetlabs-inifile-2.2.1/spec/acceptance/nodesets0040755005276200011600000000000013265372213017071 5ustar00puppetlabs-inifile-2.2.1/spec/acceptance/nodesets/centos-7-x64.yml0100644005276200011600000000025613261374561021755 0ustar00HOSTS: centos-7-x64: roles: - agent - default platform: el-7-x86_64 hypervisor: vagrant box: puppetlabs/centos-7.2-64-nocm CONFIG: type: foss puppetlabs-inifile-2.2.1/spec/acceptance/nodesets/debian-8-x64.yml0100644005276200011600000000026113261374561021701 0ustar00HOSTS: debian-8-x64: roles: - agent - default platform: debian-8-amd64 hypervisor: vagrant box: puppetlabs/debian-8.2-64-nocm CONFIG: type: foss puppetlabs-inifile-2.2.1/spec/acceptance/nodesets/default.yml0100644005276200011600000000027213261374561021321 0ustar00HOSTS: ubuntu-1404-x64: roles: - agent - default platform: ubuntu-14.04-amd64 hypervisor: vagrant box: puppetlabs/ubuntu-14.04-64-nocm CONFIG: type: foss puppetlabs-inifile-2.2.1/spec/acceptance/nodesets/docker0040755005276200011600000000000013265372213020340 5ustar00puppetlabs-inifile-2.2.1/spec/acceptance/nodesets/docker/centos-7.yml0100644005276200011600000000057513261374561022611 0ustar00HOSTS: centos-7-x64: platform: el-7-x86_64 hypervisor: docker image: centos:7 docker_preserve_image: true docker_cmd: '["/usr/sbin/init"]' # install various tools required to get the image up to usable levels docker_image_commands: - 'yum install -y crontabs tar wget openssl sysvinit-tools iproute which initscripts' CONFIG: trace_limit: 200 puppetlabs-inifile-2.2.1/spec/acceptance/nodesets/docker/debian-8.yml0100644005276200011600000000054413261374561022535 0ustar00HOSTS: debian-8-x64: platform: debian-8-amd64 hypervisor: docker image: debian:8 docker_preserve_image: true docker_cmd: '["/sbin/init"]' docker_image_commands: - 'apt-get update && apt-get install -y net-tools wget locales strace lsof && echo "en_US.UTF-8 UTF-8" > /etc/locale.gen && locale-gen' CONFIG: trace_limit: 200 puppetlabs-inifile-2.2.1/spec/acceptance/nodesets/docker/ubuntu-14.04.yml0100644005276200011600000000073213261374561023133 0ustar00HOSTS: ubuntu-1404-x64: platform: ubuntu-14.04-amd64 hypervisor: docker image: ubuntu:14.04 docker_preserve_image: true docker_cmd: '["/sbin/init"]' docker_image_commands: # ensure that upstart is booting correctly in the container - 'rm /usr/sbin/policy-rc.d && rm /sbin/initctl && dpkg-divert --rename --remove /sbin/initctl && apt-get update && apt-get install -y net-tools wget && locale-gen en_US.UTF-8' CONFIG: trace_limit: 200 puppetlabs-inifile-2.2.1/spec/classes0040755005276200011600000000000013265372213014614 5ustar00puppetlabs-inifile-2.2.1/spec/classes/create_ini_settings_test_spec.rb0100644005276200011600000000143413261374561023316 0ustar00require 'spec_helper' # end-to-end test of the create_init_settings function describe 'create_ini_settings_test' do it { is_expected.to have_ini_setting_resource_count(3) } it { is_expected.to contain_ini_setting('/tmp/foo.ini [section1] setting1').with( ensure: 'present', section: 'section1', setting: 'setting1', value: 'val1', path: '/tmp/foo.ini' ) } it { is_expected.to contain_ini_setting('/tmp/foo.ini [section2] setting2').with( ensure: 'present', section: 'section2', setting: 'setting2', value: 'val2', path: '/tmp/foo.ini' ) } it { is_expected.to contain_ini_setting('/tmp/foo.ini [section2] setting3').with( ensure: 'absent', section: 'section2', setting: 'setting3', path: '/tmp/foo.ini' ) } end puppetlabs-inifile-2.2.1/spec/classes/create_multiple_ini_settings_spec.rb0100644005276200011600000000112213265372073024164 0ustar00require 'spec_helper' describe 'create_multiple_ini_settings' do context 'on a non-Windows platform', if: !Puppet::Util::Platform.windows? do let(:facts) do { 'os' => { 'family' => 'RedHat', 'release' => { 'major' => '7', 'minor' => '1', 'full' => '7.1.1503' } } } end it { is_expected.to compile } end context 'on a Windows platform', if: Puppet::Util::Platform.windows? do let(:facts) do { 'osfamily' => 'windows' } end it { is_expected.to compile } end end puppetlabs-inifile-2.2.1/spec/classes/inherit_test1_spec.rb0100644005276200011600000000035713261374561021022 0ustar00require 'spec_helper' # We can't really test much here, apart from the type roundtrips though the # parser OK. describe 'inherit_test1' do it { is_expected.to contain_inherit_ini_setting('valid_type').with('value' => 'true') } end puppetlabs-inifile-2.2.1/spec/fixtures0040755005276200011600000000000013265372213015030 5ustar00puppetlabs-inifile-2.2.1/spec/fixtures/create_ini_settings_test0040755005276200011600000000000013265372213022111 5ustar00puppetlabs-inifile-2.2.1/spec/fixtures/create_ini_settings_test/manifests0040755005276200011600000000000013265372213024102 5ustar00puppetlabs-inifile-2.2.1/spec/fixtures/create_ini_settings_test/manifests/init.pp0100644005276200011600000000046713261374561025475 0ustar00# simple test class class create_ini_settings_test { $settings = { section1 => { setting1 => val1 }, section2 => { setting2 => val2, setting3 => { ensure => absent } } } $defaults = { path => '/tmp/foo.ini' } create_ini_settings($settings,$defaults) } puppetlabs-inifile-2.2.1/spec/fixtures/create_multiple_ini_settings0040755005276200011600000000000013265372213022765 5ustar00puppetlabs-inifile-2.2.1/spec/fixtures/create_multiple_ini_settings/manifests0040755005276200011600000000000013265372213024756 5ustar00puppetlabs-inifile-2.2.1/spec/fixtures/create_multiple_ini_settings/manifests/init.pp0100644005276200011600000000063113265372073026342 0ustar00# Manifest creating multiple ini_settings class create_multiple_ini_settings { if $facts['osfamily'] == 'windows' { $defaults = { 'path' => 'C:/tmp/foo.ini' } } else { $defaults = { 'path' => '/tmp/foo.ini' } } $example = { 'section1' => { 'setting1' => 'value1', 'settings2' => { 'ensure' => 'absent' } } } create_ini_settings($example, $defaults) } puppetlabs-inifile-2.2.1/spec/fixtures/inherit_ini_setting0040755005276200011600000000000013265372213021066 5ustar00puppetlabs-inifile-2.2.1/spec/fixtures/inherit_ini_setting/lib0040755005276200011600000000000013265372213021634 5ustar00puppetlabs-inifile-2.2.1/spec/fixtures/inherit_ini_setting/lib/puppet0040755005276200011600000000000013265372213023151 5ustar00puppetlabs-inifile-2.2.1/spec/fixtures/inherit_ini_setting/lib/puppet/provider0040755005276200011600000000000013265372213025003 5ustar00puppetlabs-inifile-2.2.1/spec/fixtures/inherit_ini_setting/lib/puppet/provider/inherit_ini_setting0040755005276200011600000000000013265372213031041 5ustar00spec/fixtures/inherit_ini_setting/lib/puppet/provider/inherit_ini_setting/ini_setting.rb0100644005276200011600000000060113261374561033700 0ustar00puppetlabs-inifile-2.2.1Puppet::Type.type(:inherit_ini_setting).provide( :ini_setting, parent: Puppet::Type.type(:ini_setting).provider(:ruby), ) do def section '' # all global end # This type has no sections def self.namevar(_section_name, setting) setting end def self.file_path File.expand_path(File.dirname(__FILE__) + '/../../../../../../tmp/inherit_inifile.cfg') end end puppetlabs-inifile-2.2.1/spec/fixtures/inherit_ini_setting/lib/puppet/type0040755005276200011600000000000013265372213024132 5ustar00puppetlabs-inifile-2.2.1/spec/fixtures/inherit_ini_setting/lib/puppet/type/inherit_ini_setting.rb0100644005276200011600000000017013261374561030573 0ustar00Puppet::Type.newtype(:inherit_ini_setting) do ensurable newparam(:setting, namevar: true) newproperty(:value) end puppetlabs-inifile-2.2.1/spec/fixtures/inherit_test10040755005276200011600000000000013265372213017612 5ustar00puppetlabs-inifile-2.2.1/spec/fixtures/inherit_test1/manifests0040755005276200011600000000000013265372213021603 5ustar00puppetlabs-inifile-2.2.1/spec/fixtures/inherit_test1/manifests/init.pp0100644005276200011600000000017013261374561023165 0ustar00# Manufest inheriting ini_settings class inherit_test1 { inherit_ini_setting { 'valid_type': value => true, } } puppetlabs-inifile-2.2.1/spec/functions0040755005276200011600000000000013265372213015167 5ustar00puppetlabs-inifile-2.2.1/spec/functions/create_ini_settings_spec.rb0100644005276200011600000000204113265372073022625 0ustar00require '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 { is_expected.to run.with_params.and_raise_error(Puppet::ParseError, %r{0 for 1 or 2}) } it { is_expected.to run.with_params(1, 2, 3).and_raise_error(Puppet::ParseError, %r{3 for 1 or 2}) } it { is_expected.to run.with_params('foo').and_raise_error(Puppet::ParseError, %r{Requires all arguments}) } it { is_expected.to run.with_params({}, 'foo').and_raise_error(Puppet::ParseError, %r{Requires all arguments}) } it { is_expected.to run.with_params({}) } it { is_expected.to run.with_params({}, {}) } it { is_expected.to run.with_params('section' => { 'setting' => 'value' }).and_raise_error(Puppet::ParseError, %r{must pass the path parameter}) } it { is_expected.to run.with_params(1 => 2).and_raise_error(Puppet::ParseError, %r{Section 1 must contain a Hash}) } end end puppetlabs-inifile-2.2.1/spec/spec_helper.rb0100644005276200011600000000144313261374561016057 0ustar00require 'puppetlabs_spec_helper/module_spec_helper' require 'rspec-puppet-facts' include RspecPuppetFacts default_facts = { puppetversion: Puppet.version, facterversion: Facter.version, } default_facts_path = File.expand_path(File.join(File.dirname(__FILE__), 'default_facts.yml')) default_module_facts_path = File.expand_path(File.join(File.dirname(__FILE__), 'default_module_facts.yml')) if File.exist?(default_facts_path) && File.readable?(default_facts_path) default_facts.merge!(YAML.safe_load(File.read(default_facts_path))) end if File.exist?(default_module_facts_path) && File.readable?(default_module_facts_path) default_facts.merge!(YAML.safe_load(File.read(default_module_facts_path))) end RSpec.configure do |c| c.default_facts = default_facts end require 'spec_helper_local' puppetlabs-inifile-2.2.1/spec/spec_helper_acceptance.rb0100644005276200011600000000102013261374561020214 0ustar00require 'beaker-rspec/spec_helper' require 'beaker-rspec/helpers/serverspec' require 'beaker/puppet_install_helper' require 'beaker/module_install_helper' run_puppet_install_helper install_ca_certs unless ENV['PUPPET_INSTALL_TYPE'] =~ %r{pe}i install_module_on(hosts) install_module_dependencies_on(hosts) RSpec.configure do |c| c.filter_run focus: true c.run_all_when_everything_filtered = true # Readable test descriptions c.formatter = :documentation c.treat_symbols_as_metadata_keys_with_true_values = true end puppetlabs-inifile-2.2.1/spec/spec_helper_local.rb0100644005276200011600000000007213261374561017226 0ustar00RSpec.configure do |config| config.mock_with :rspec end puppetlabs-inifile-2.2.1/spec/unit0040755005276200011600000000000013265372213014136 5ustar00puppetlabs-inifile-2.2.1/spec/unit/puppet0040755005276200011600000000000013265372213015453 5ustar00puppetlabs-inifile-2.2.1/spec/unit/puppet/provider0040755005276200011600000000000013265372213017305 5ustar00puppetlabs-inifile-2.2.1/spec/unit/puppet/provider/ini_setting0040755005276200011600000000000013265372213021621 5ustar00puppetlabs-inifile-2.2.1/spec/unit/puppet/provider/ini_setting/inheritance_spec.rb0100644005276200011600000000350213261374561025531 0ustar00require 'spec_helper' # This is a reduced version of ruby_spec.rb just to ensure we can subclass as # documented $LOAD_PATH << './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) expect(File.read(tmpfile)).to eq(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 'parses nothing when the file is empty' do provider_class.stubs(:file_path).returns(tmpfile) expect(provider_class.instances).to eq([]) end context 'when the file has contents' do let(:orig_content) do <<-EOS # A comment red = blue green = purple EOS end it 'parses the results' do provider_class.stubs(:file_path).returns(tmpfile) instances = provider_class.instances expect(instances.size).to eq(2) # inherited version of namevar flattens the names names = instances.map do |instance| instance.instance_variable_get(:@property_hash)[:name] end # rubocop:disable Style/BlockDelimiters expect(names.sort).to eq(%w[green red]) end end end context 'when ensuring that a setting is present' do let(:orig_content) { '' } it 'adds 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", tmpfile) end end end puppetlabs-inifile-2.2.1/spec/unit/puppet/provider/ini_setting/ruby_spec.rb0100644005276200011600000011725513261374561024234 0ustar00require '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) do { title: 'ini_setting_ensure_present_test', path: tmpfile, section: 'section2', } end def validate_file(expected_content, tmpfile) expect(File.read(tmpfile)).to eq(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 'fails 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 child_one = Class.new(provider_class) do def self.file_path emptyfile end end it 'returns [] when file is empty' do child_one.stubs(:file_path).returns(emptyfile) expect(child_one.instances).to eq([]) end child_two = Class.new(provider_class) do def self.file_path '/some/file/path' end end it 'overrides the provider instances file_path' do resource = Puppet::Type::Ini_setting.new(common_params) provider = child_two.new(resource) expect(provider.file_path).to eq('/some/file/path') end end context 'when file has contecnts' do let(:orig_content) do <<-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 end it 'is 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) expect(child_three.instances.size).to eq(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 expect(ensure_array.uniq).to eq([:present]) expect((real_array - expected_array) && (expected_array - real_array)).to eq([]) end # rubocop:enable RSpec/ExampleLength # rubocop:enable RSpec/MultipleExpectations end end # rubocop:disable Layout/IndentHeredoc : Altering the Indent causes test failures context 'when ensuring that a setting is present' do let(:orig_content) do <<-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 end expected_content_one = <<-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 it 'adds 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) expect(provider.exists?).to be false provider.create validate_file(expected_content_one, tmpfile) end expected_content_two = <<-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 it 'adds 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) expect(provider.exists?).to be false provider.create validate_file(expected_content_two, tmpfile) end expected_content_three = <<-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 indented = weirdly EOS it 'adds a missing setting to the correct section with indent_char' do resource = Puppet::Type::Ini_setting.new(common_params.merge(section: 'nonstandard', setting: 'indented', value: 'weirdly', section_prefix: '-', section_suffix: '-', indent_char: "\t")) provider = described_class.new(resource) expect(provider.exists?).to be false provider.create validate_file(expected_content_three, tmpfile) end expected_content_four = <<-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 indented = weirdly EOS it 'adds a missing setting to the correct section indented by indent_char * indent_width' do resource = Puppet::Type::Ini_setting.new(common_params.merge(section: 'nonstandard', setting: 'indented', value: 'weirdly', section_prefix: '-', section_suffix: '-', indent_char: "\t", indent_width: 4)) provider = described_class.new(resource) expect(provider.exists?).to be false provider.create validate_file(expected_content_four, tmpfile) end expected_content_five = <<-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 indented = weirdly EOS it 'treats a string indent_width as an integer' do resource = Puppet::Type::Ini_setting.new(common_params.merge(section: 'nonstandard', setting: 'indented', value: 'weirdly', section_prefix: '-', section_suffix: '-', indent_char: "\t", indent_width: '4')) provider = described_class.new(resource) expect(provider.exists?).to be false provider.create validate_file(expected_content_five, tmpfile) end expected_content_six = <<-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 it 'adds 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) expect(provider.exists?).to be false provider.create validate_file(expected_content_six, tmpfile) end expected_content_seven = <<-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 it 'modifies 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) expect(provider).to be_exists provider.value = 'bazvalue2' validate_file(expected_content_seven, tmpfile) end expected_content_eight = <<-EOS # This is a comment [section1] ; This is also a comment foo=foovalue bar = barvalue master = false [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 'modifies an existing setting with a different boolean value' do resource = Puppet::Type::Ini_setting.new(common_params.merge(section: 'section1', setting: 'master', value: false)) provider = described_class.new(resource) expect(provider.exists?).to be true transaction = instance_double('transaction', persistence: true) expect(Puppet::Transaction::ResourceHarness.new(transaction).evaluate(provider.resource).out_of_sync).to eq(true) validate_file(expected_content_eight, tmpfile) end # rubocop:enable RSpec/MultipleExpectations : Unable to reduce without altering test expected_content_nine = <<-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 it 'modifies 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) expect(provider.exists?).to be true provider.value = 'orange' validate_file(expected_content_nine, tmpfile) end expected_content_ten = <<-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 it 'modifies 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) expect(provider.value).to eq('bar') provider.value = 'foo' validate_file(expected_content_ten, tmpfile) end expected_content_eleven = <<-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 it 'is 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) expect(provider.value).to eq('http://192.168.1.1:8080') provider.value = 'http://192.168.0.1:8080' validate_file(expected_content_eleven, tmpfile) end expected_content_twelve = <<-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 it 'is 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) expect(provider.value).to eq('purple') provider.value = 'http://192.168.0.1:8080' validate_file(expected_content_twelve, tmpfile) end it 'recognizes 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) expect(provider.exists?).to be true end it 'recognizes 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) expect(provider.exists?).to be true end expected_content_thirteen = <<-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 it 'adds 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) expect(provider.exists?).to be false provider.create validate_file(expected_content_thirteen, tmpfile) end expected_content_fourteen = <<-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 it 'adds 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) expect(provider).not_to be_exists provider.create validate_file(expected_content_fourteen, tmpfile) end expected_content_fifteen = <<-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 it 'adds 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) expect(provider.exists?).to be false provider.create validate_file(expected_content_fifteen, tmpfile) end expected_content_sixteen = <<-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 it 'adds 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) expect(provider.exists?).to be false provider.create validate_file(expected_content_sixteen, tmpfile) end validate_one = ' [section1] setting1 = hellowworld ' it 'adds 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) expect(provider.exists?).to be false provider.create validate_file(validate_one, emptyfile) end validate_two = ' -section1- setting1 = hellowworld ' it 'adds 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) expect(provider.exists?).to be false provider.create validate_file(validate_two, emptyfile) end validate_three = ' [section:subsection] setting1 = hellowworld ' it 'adds 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) expect(provider.exists?).to be false provider.create validate_file(validate_three, emptyfile) end validate_four = ' -section:subsection- setting1 = hellowworld ' it 'adds 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) expect(provider.exists?).to be false provider.create validate_file(validate_four, emptyfile) end it 'is 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) expect(provider.value).to eq('true') end end context 'when dealing with a global section' do let(:orig_content) do <<-EOS # This is a comment foo=blah [section2] foo = http://192.168.1.1:8080 ; yet another comment EOS end expected_content_one = <<-EOS # This is a comment foo=blah bar = yippee [section2] foo = http://192.168.1.1:8080 ; yet another comment EOS it "adds 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) expect(provider.exists?).to be false provider.create validate_file(expected_content_one, tmpfile) end expected_content_two = <<-EOS # This is a comment foo=yippee [section2] foo = http://192.168.1.1:8080 ; yet another comment EOS it 'modifies 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) expect(provider.value).to eq('blah') provider.value = 'yippee' validate_file(expected_content_two, tmpfile) end it 'recognizes 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) expect(provider.exists?).to be true end end context 'when the first line of the file is a section' do let(:orig_content) do <<-EOS [section2] foo = http://192.168.1.1:8080 EOS end expected_content_one = <<-EOS foo = yippee [section2] foo = http://192.168.1.1:8080 EOS it 'is 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) expect(provider.exists?).to be false provider.create validate_file(expected_content_one, tmpfile) end expected_content_two = <<-EOS [section2] foo = yippee EOS it 'modifies an existing setting' do resource = Puppet::Type::Ini_setting.new(common_params.merge(section: 'section2', setting: 'foo', value: 'yippee')) provider = described_class.new(resource) expect(provider.value).to eq('http://192.168.1.1:8080') provider.value = 'yippee' validate_file(expected_content_two, tmpfile) end expected_content_three = <<-EOS [section2] foo = http://192.168.1.1:8080 bar = baz EOS it 'adds a new setting' do resource = Puppet::Type::Ini_setting.new(common_params.merge(section: 'section2', setting: 'bar', value: 'baz')) provider = described_class.new(resource) expect(provider.exists?).to be false provider.create validate_file(expected_content_three, tmpfile) end end context 'when overriding the separator' do let(:orig_content) do <<-EOS [section2] foo=bar EOS end expected_content_one = <<-EOS [section2] foo=yippee EOS it 'modifies 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) expect(provider.value).to eq('bar') provider.value = 'yippee' validate_file(expected_content_one, tmpfile) end end context 'when overriding the separator to something other than =' do let(:orig_content) do <<-EOS [section2] foo: bar EOS end expected_content_one = <<-EOS [section2] foo: yippee EOS it 'modifies 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) expect(provider.value).to eq('bar') provider.value = 'yippee' validate_file(expected_content_one, tmpfile) end expected_content_two = <<-EOS [section2] foo: bar bar: baz EOS it 'adds 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) expect(provider.exists?).to be false provider.create validate_file(expected_content_two, tmpfile) end end context 'when overriding the separator to a space' do let(:orig_content) do <<-EOS [section2] foo bar EOS end expected_content_one = <<-EOS [section2] foo yippee EOS it 'modifies 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) expect(provider.value).to eq('bar') provider.value = 'yippee' validate_file(expected_content_one, tmpfile) end expected_content_two = <<-EOS [section2] foo bar bar baz EOS it 'adds 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) expect(provider.exists?).to be false provider.create validate_file(expected_content_two, tmpfile) end end context 'when ensuring that a setting is absent' do let(:orig_content) do <<-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 [section3] # com = ment uncom = ment [section4] uncom = ment [section:sub] subby=bar #another comment ; yet another comment -nonstandard- shoes = purple EOS end expected_content_one = <<-EOS [section1] ; This is also a comment bar = barvalue master = true [section2] foo= foovalue2 baz=bazvalue url = http://192.168.1.1:8080 [section3] # com = ment uncom = ment [section4] uncom = ment [section:sub] subby=bar #another comment ; yet another comment -nonstandard- shoes = purple EOS it 'removes 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) expect(provider.exists?).to be true provider.destroy validate_file(expected_content_one, tmpfile) end expected_content_two = <<-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 [section3] # com = ment uncom = ment [section4] uncom = ment [section:sub] subby=bar #another comment ; yet another comment EOS it 'removes 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) expect(provider.exists?).to be true provider.destroy validate_file(expected_content_two, tmpfile) end expected_content_three = <<-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 [section3] # com = ment uncom = ment [section4] uncom = ment [section:sub] subby=bar #another comment ; yet another comment -nonstandard- shoes = purple EOS it 'does 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) expect(provider.exists?).to be false provider.destroy validate_file(expected_content_three, tmpfile) end expected_content_four = <<-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 [section3] # com = ment uncom = ment [section4] uncom = ment [section:sub] subby=bar #another comment ; yet another comment -nonstandard- shoes = purple EOS it 'does 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) expect(provider.exists?).to be false provider.destroy validate_file(expected_content_four, tmpfile) end expected_content_five = <<-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 [section3] # com = ment [section4] uncom = ment [section:sub] subby=bar #another comment ; yet another comment -nonstandard- shoes = purple EOS it 'does not remove a section when the last uncommented setting is removed if there are comments' do resource = Puppet::Type::Ini_setting.new(common_params.merge(section: 'section3', setting: 'uncom', ensure: 'absent')) provider = described_class.new(resource) expect(provider.exists?).to be true provider.destroy validate_file(expected_content_five, tmpfile) end expected_content_six = <<-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 [section3] # com = ment uncom = ment [section:sub] subby=bar #another comment ; yet another comment -nonstandard- shoes = purple EOS it 'removes the section when removing the last line in the section' do resource = Puppet::Type::Ini_setting.new(common_params.merge(section: 'section4', setting: 'uncom', ensure: 'absent')) provider = described_class.new(resource) expect(provider.exists?).to be true provider.destroy validate_file(expected_content_six, tmpfile) end end context 'when dealing with indentation in sections' do let(:orig_content) do <<-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 end expected_content_one = <<-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 it 'adds 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) expect(provider.exists?).to be false provider.create validate_file(expected_content_one, tmpfile) end expected_content_two = <<-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 it 'updates 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) expect(provider.exists?).to be true provider.create validate_file(expected_content_two, tmpfile) end expected_content_three = <<-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 it 'adds 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) expect(provider.exists?).to be false provider.create validate_file(expected_content_three, tmpfile) end expected_content_four = <<-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 it 'updates 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) expect(provider.exists?).to be true provider.create validate_file(expected_content_four, tmpfile) end expected_content_five = <<-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 it 'adds 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) expect(provider.exists?).to be false provider.create validate_file(expected_content_five, tmpfile) end expected_content_six = <<-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 it 'updates 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) expect(provider.exists?).to be true provider.create validate_file(expected_content_six, tmpfile) end expected_content_seven = <<-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 it 'updates an existing setting at the previous indentation regardless of indent_char and indent_width settings' do resource = Puppet::Type::Ini_setting.new(common_params.merge(section: 'section:sub', setting: 'fleezy', value: 'flam2', indent_char: 'ignore this', indent_width: 10)) provider = described_class.new(resource) expect(provider.exists?).to be true provider.create validate_file(expected_content_seven, tmpfile) end end context 'when dealing settings that have a commented version present' do let(:orig_content) do <<-EOS [section1] # foo=foovalue bar=barvalue foo = foovalue2 [section2] # foo = foovalue ;bar=barvalue blah = blah #baz= EOS end expected_content_eight = <<-EOS [section1] # foo=foovalue bar=barvalue foo = foovalue2 [section2] # foo = foovalue foo = foo3 ;bar=barvalue blah = blah #baz= EOS it 'adds 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) expect(provider.exists?).to be false provider.create validate_file(expected_content_eight, tmpfile) end expected_content_nine = <<-EOS [section1] # foo=foovalue bar=barvalue foo = foo3 [section2] # foo = foovalue ;bar=barvalue blah = blah #baz= EOS it 'updates 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) expect(provider.exists?).to be true provider.create validate_file(expected_content_nine, tmpfile) end expected_content_ten = <<-EOS [section1] # foo=foovalue bar=barvalue foo = foovalue2 [section2] # foo = foovalue ;bar=barvalue bar = bar3 blah = blah #baz= EOS it 'adds 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) expect(provider.exists?).to be false provider.create validate_file(expected_content_ten, tmpfile) end expected_content_four = <<-EOS [section1] # foo=foovalue bar=barvalue foo = foovalue2 [section2] # foo = foovalue ;bar=barvalue blah = blah #baz= baz = bazvalue EOS it 'adds 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) expect(provider.exists?).to be false provider.create validate_file(expected_content_four, tmpfile) end context 'when a section only contains comments' do let(:orig_content) do <<-EOS [section1] # foo=foovalue # bar=bar2 EOS end expected_content_one = <<-EOS [section1] # foo=foovalue foo = foovalue2 # bar=bar2 EOS it 'is 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) expect(provider.exists?).to be false provider.create validate_file(expected_content_one, tmpfile) end expected_content_two = <<-EOS [section1] # foo=foovalue # bar=bar2 bar = barvalue2 EOS it 'is 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) expect(provider.exists?).to be false provider.create validate_file(expected_content_two, tmpfile) end end context 'when sections have spaces and dashes' do let(:orig_content) do <<-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 end expected_content_one = <<-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 it 'adds 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) expect(provider.exists?).to be false provider.create validate_file(expected_content_one, tmpfile) 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 expected_content_one = <<-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 it 'adds 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) expect(provider.exists?).to be false provider.create validate_file(expected_content_one, tmpfile) end end # rubocop:enable Layout/IndentHeredoc end puppetlabs-inifile-2.2.1/spec/unit/puppet/provider/ini_subsetting0040755005276200011600000000000013265372213022333 5ustar00puppetlabs-inifile-2.2.1/spec/unit/puppet/provider/ini_subsetting/ruby_spec.rb0100644005276200011600000002557213261374561024746 0ustar00require '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) expect(File.read(tmpfile)).to eq 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) do { title: 'ini_setting_ensure_present_test', path: tmpfile, section: '', key_val_separator: '=', setting: 'JAVA_ARGS', } end let(:orig_content) do <<-EOS JAVA_ARGS="-Xmx192m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/pe-puppetdb/puppetdb-oom.hprof" EOS end expected_content_one = <<-EOS JAVA_ARGS="-Xmx192m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/pe-puppetdb/puppetdb-oom.hprof -Xms128m" EOS it 'adds a missing subsetting' do resource = Puppet::Type::Ini_subsetting.new(common_params.merge(subsetting: '-Xms', value: '128m')) provider = described_class.new(resource) expect(provider.exists?).to be_nil provider.create validate_file(expected_content_one, tmpfile) end expected_content_two = <<-EOS JAVA_ARGS="-Xms128m -Xmx192m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/pe-puppetdb/puppetdb-oom.hprof" EOS it 'adds a missing subsetting element at the beginning of the line' do resource = Puppet::Type::Ini_subsetting.new(common_params.merge(subsetting: '-Xms', value: '128m', insert_type: :start)) provider = described_class.new(resource) expect(provider.exists?).to be_nil provider.create validate_file(expected_content_two, tmpfile) end expected_content_three = <<-EOS JAVA_ARGS="-Xmx192m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/pe-puppetdb/puppetdb-oom.hprof -Xms128m" EOS it 'adds a missing subsetting element at the end of the line' do resource = Puppet::Type::Ini_subsetting.new(common_params.merge(subsetting: '-Xms', value: '128m', insert_type: :end)) provider = described_class.new(resource) expect(provider.exists?).to be_nil provider.create validate_file(expected_content_three, tmpfile) end expected_content_four = <<-EOS JAVA_ARGS="-Xmx192m -Xms128m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/pe-puppetdb/puppetdb-oom.hprof" EOS it 'adds a missing subsetting element after the given item' do resource = Puppet::Type::Ini_subsetting.new(common_params.merge(subsetting: '-Xms', value: '128m', insert_type: :after, insert_value: '-Xmx')) provider = described_class.new(resource) expect(provider.exists?).to be_nil provider.create validate_file(expected_content_four, tmpfile) end expected_content_five = <<-EOS JAVA_ARGS="-Xms128m -Xmx192m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/pe-puppetdb/puppetdb-oom.hprof" EOS it 'adds a missing subsetting element before the given item' do resource = Puppet::Type::Ini_subsetting.new(common_params.merge(subsetting: '-Xms', value: '128m', insert_type: :before, insert_value: '-Xmx')) provider = described_class.new(resource) expect(provider.exists?).to be_nil provider.create validate_file(expected_content_five, tmpfile) end expected_content_six = <<-EOS JAVA_ARGS="-Xmx192m -Xms128m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/pe-puppetdb/puppetdb-oom.hprof" EOS it 'adds a missing subsetting element at the given index' do resource = Puppet::Type::Ini_subsetting.new(common_params.merge(subsetting: '-Xms', value: '128m', insert_type: :index, insert_value: '1')) provider = described_class.new(resource) expect(provider.exists?).to be_nil provider.create validate_file(expected_content_six, tmpfile) end expected_content_seven = <<-EOS JAVA_ARGS="-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/pe-puppetdb/puppetdb-oom.hprof" EOS it 'removes an existing subsetting' do resource = Puppet::Type::Ini_subsetting.new(common_params.merge(subsetting: '-Xmx')) provider = described_class.new(resource) expect(provider.exists?).to eq '192m' provider.destroy validate_file(expected_content_seven, tmpfile) end expected_content_eight = <<-EOS JAVA_ARGS="-Xmx192m" EOS it 'is able to remove several subsettings with the same name' do resource = Puppet::Type::Ini_subsetting.new(common_params.merge(subsetting: '-XX')) provider = described_class.new(resource) expect(provider.exists?).to eq ':+HeapDumpOnOutOfMemoryError' provider.destroy validate_file(expected_content_eight, tmpfile) end expected_content_nine = <<-EOS JAVA_ARGS="-Xmx256m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/pe-puppetdb/puppetdb-oom.hprof" EOS it 'modifies an existing subsetting' do resource = Puppet::Type::Ini_subsetting.new(common_params.merge(subsetting: '-Xmx', value: '256m')) provider = described_class.new(resource) expect(provider.exists?).to eq '192m' provider.value = '256m' validate_file(expected_content_nine, tmpfile) end expected_content_ten = <<-EOS JAVA_ARGS="-Xmx192m -XXtest -XXtest" EOS it 'is able to modify several subsettings with the same name' do resource = Puppet::Type::Ini_subsetting.new(common_params.merge(subsetting: '-XX', value: 'test')) provider = described_class.new(resource) expect(provider.exists?).to eq ':+HeapDumpOnOutOfMemoryError' provider.value = 'test' validate_file(expected_content_ten, tmpfile) end end context 'when working with subsettings in files with unquoted settings values' do let(:common_params) do { title: 'ini_setting_ensure_present_test', path: tmpfile, section: 'master', setting: 'reports', } end let(:orig_content) do <<-EOS [master] reports = http,foo EOS end expected_content_one = <<-EOS [master] reports = foo EOS it 'removes an existing subsetting' do resource = Puppet::Type::Ini_subsetting.new(common_params.merge(subsetting: 'http', subsetting_separator: ',')) provider = described_class.new(resource) expect(provider.exists?).to eq '' provider.destroy validate_file(expected_content_one, tmpfile) end expected_content_two = <<-EOS [master] reports = http,foo,puppetdb EOS it "adds 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) expect(provider.exists?).to be_nil provider.value = '' validate_file(expected_content_two, tmpfile) end expected_content_three = <<-EOS [master] reports = http,foo somenewsetting = puppetdb EOS it "adds 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) expect(provider.exists?).to be_nil provider.value = '' validate_file(expected_content_three, tmpfile) end end context 'when working with subsettings in files with use_exact_match' do let(:common_params) do { title: 'ini_setting_ensure_present_test', path: tmpfile, section: 'master', setting: 'reports', use_exact_match: true, } end let(:orig_content) do <<-EOS [master] reports = http,foo EOS end expected_content_one = <<-EOS [master] reports = http,foo,fo EOS it "adds 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(expected_content_one, tmpfile) end expected_content_two = <<-EOS [master] reports = http,foo EOS it 'does 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(expected_content_two, tmpfile) end end context 'when working with subsettings in files with subsetting_key_val_separator' do let(:common_params) do { title: 'ini_setting_ensure_present_test', path: tmpfile, section: 'master', setting: 'reports', subsetting_separator: ',', subsetting_key_val_separator: ':', } end let(:orig_content) do <<-EOS [master] reports = a:1,b:2 EOS end expected_content_one = <<-EOS [master] reports = a:1,b:2,c:3 EOS it "adds a new subsetting when the 'parent' setting already exists" do resource = Puppet::Type::Ini_subsetting.new(common_params.merge(subsetting: 'c', value: '3')) provider = described_class.new(resource) provider.value = '3' validate_file(expected_content_one, tmpfile) end expected_content_two = <<-EOS [master] reports = a:1,b:2 somenewsetting = c:3 EOS it "adds a new subsetting when the 'parent' setting does not already exist" do resource = Puppet::Type::Ini_subsetting.new(common_params.merge(subsetting: 'c', value: '3', setting: 'somenewsetting')) provider = described_class.new(resource) expect(provider.exists?).to be_nil provider.value = '3' validate_file(expected_content_two, tmpfile) end expected_content_three = <<-EOS [master] reports = a:1 EOS it 'is able to remove the existing subsetting' do resource = Puppet::Type::Ini_subsetting.new(common_params.merge(subsetting: 'b')) provider = described_class.new(resource) expect(provider.exists?).to eq '2' provider.destroy validate_file(expected_content_three, tmpfile) end expected_content_four = <<-EOS [master] reports = a:1,b:5 EOS it 'is able to modify the existing subsetting' do resource = Puppet::Type::Ini_subsetting.new(common_params.merge(subsetting: 'b', value: '5')) provider = described_class.new(resource) expect(provider.exists?).to eq '2' provider.value = '5' validate_file(expected_content_four, tmpfile) end end end puppetlabs-inifile-2.2.1/spec/unit/puppet/type0040755005276200011600000000000013265372213016434 5ustar00puppetlabs-inifile-2.2.1/spec/unit/puppet/type/ini_setting_spec.rb0100644005276200011600000001146713265372073022400 0ustar00require 'spec_helper' ini_setting = Puppet::Type.type(:ini_setting) describe ini_setting do describe 'path validation' do subject { -> { described_class.new(name: 'foo', path: path) } } context 'on posix platforms' do before(:each) do Puppet.features.stub(:posix?) { true } Puppet.features.stub(:microsoft_windows?) { false } Puppet::Util::Platform.stub(:windows?) { false } end context 'with an absolute path' do let(:path) { '/absolute/path' } it { is_expected.not_to raise_exception } end context 'with a relative path' do let(:path) { 'relative/path' } it { is_expected.to raise_exception } end end context 'on windows platforms' do before(:each) do Puppet.features.stub(:posix?) { false } Puppet.features.stub(:microsoft_windows?) { true } Puppet::Util::Platform.stub(:windows?) { true } end context 'with an absolute path with front slashes' do let(:path) { 'c:/absolute/path' } it { is_expected.not_to raise_exception } end context 'with an absolute path with backslashes' do let(:path) { 'c:\absolute\path' } it { is_expected.not_to raise_exception } end context 'with an absolute path with mixed slashes' do let(:path) { 'c:/absolute\path' } it { is_expected.not_to raise_exception } end context 'with a relative path with front slashes' do let(:path) { 'relative/path' } it { is_expected.to raise_exception } end context 'with a relative path with back slashes' do let(:path) { 'relative\path' } it { is_expected.to raise_exception } end end # rubocop:enable RSpec/NestedGroups end [true, false].product([true, false, 'true', 'false', 'md5', :md5]).each do |cfg, param| describe "when Puppet[:show_diff] is #{cfg} and show_diff => #{param}" do before(:each) do Puppet[:show_diff] = cfg end let(:value) { described_class.new(name: 'foo', value: 'whatever', show_diff: param).property(:value) } if cfg && [true, 'true'].include?(param) it 'displays diff' do expect(value.change_to_s('not_secret', 'at_all')).to include('not_secret', 'at_all') end it 'tells current value' do expect(value.is_to_s('not_secret_at_all')).to eq('not_secret_at_all') end it 'tells new value' do expect(value.should_to_s('not_secret_at_all')).to eq('not_secret_at_all') end elsif cfg && ['md5', :md5].include?(param) it 'tells correct md5 hashes for multiple values' do expect(value.change_to_s('not_at', 'all_secret')).to include('6edef0c4f5ec664feff6ca6fbc290970', '1660308ab156754fa09af0e8dc2c6629') end it 'does not tell singular value one' do expect(value.change_to_s('not_at #', 'all_secret')).not_to include('not_at') end it 'does not tell singular value two' do expect(value.change_to_s('not_at', 'all_secret')).not_to include('all_secret') end it 'tells md5 of current value' do expect(value.is_to_s('not_at_all_secret')).to eq('{md5}858b46aee11b780b8f5c8853668efc05') end it 'does not tell the current value' do expect(value.is_to_s('not_at_all_secret')).not_to include('not_secret_at_all') end it 'tells md5 of new value' do expect(value.should_to_s('not_at_all_secret')).to eq('{md5}858b46aee11b780b8f5c8853668efc05') end it 'does not tell the new value' do expect(value.should_to_s('not_at_all_secret')).not_to include('not_secret_at_all') end else it 'tells redaction warning in place of actual values' do expect(value.change_to_s('at_all', 'not_secret')).to include('[redacted sensitive information]') end it 'does not tell actual value one' do expect(value.change_to_s('at_all', 'not_secret')).not_to include('not_secret') end it 'does not tell actual value two' do expect(value.change_to_s('at_all', 'not_secret')).not_to include('at_all') end it 'tells redaction warning in place of current value' do expect(value.is_to_s('not_secret_at_all')).to eq('[redacted sensitive information]') end it 'does not tell current value' do expect(value.is_to_s('not_secret_at_all')).not_to include('not_secret_at_all') end it 'tells redaction warning in place of new value' do expect(value.should_to_s('not_secret_at_all')).to eq('[redacted sensitive information]') end it 'does not tell new value' do expect(value.should_to_s('not_secret_at_all')).not_to include('not_secret_at_all') end end end end end puppetlabs-inifile-2.2.1/spec/unit/puppet/type/ini_subetting_spec.rb0100644005276200011600000000612513265372073022722 0ustar00require 'spec_helper' ini_subsetting = Puppet::Type.type(:ini_subsetting) describe ini_subsetting do [true, false].product([true, false, :md5]).each do |cfg, param| describe "when Puppet[:show_diff] is #{cfg} and show_diff => #{param}" do before(:each) do Puppet[:show_diff] = cfg end let(:value) { described_class.new(name: 'foo', value: 'whatever', show_diff: param).property(:value) } if cfg && param == true it 'displays diff' do expect(value.change_to_s('not_secret', 'at_all')).to include('not_secret', 'at_all') end it 'tells current value' do expect(value.is_to_s('not_secret_at_all')).to eq('not_secret_at_all') end it 'tells new value' do expect(value.should_to_s('not_secret_at_all')).to eq('not_secret_at_all') end elsif cfg && param == :md5 it 'tells correct md5 hashes for multiple values' do expect(value.change_to_s('not_secret', 'at_all')).to include('e9e8db547f8960ef32dbc34029735564', '46cd73a9509ba78c39f05faf078a8cbe') end it 'does not tell singular value one' do expect(value.change_to_s('not_secret', 'at_all')).not_to include('not_secret') end it 'does not tell singular value two' do expect(value.change_to_s('not_secret', 'at_all')).not_to include('at_all') end it 'tells md5 of current value' do expect(value.is_to_s('not_secret_at_all')).to eq('{md5}218fde79f501b8ab8d212f1059bb857f') end it 'does not tell the current value' do expect(value.is_to_s('not_secret_at_all')).not_to include('not_secret_at_all') end it 'tells md5 of new value' do expect(value.should_to_s('not_secret_at_all')).not_to include('not_secret_at_all') end it 'does not tell the new value' do expect(value.should_to_s('not_secret_at_all')).to eq('{md5}218fde79f501b8ab8d212f1059bb857f') end else it 'tells redaction warning in place of actual values' do expect(value.change_to_s('not_at', 'all_secret')).to include('[redacted sensitive information]') end it 'does not tell actual value one' do expect(value.change_to_s('not_at', 'all_secret')).not_to include('not_at') end it 'does not tell actual value two' do expect(value.change_to_s('not_at', 'all_secret')).not_to include('all_secret') end it 'tells redaction warning in place of current value' do expect(value.is_to_s('not_at_all_secret')).to eq('[redacted sensitive information]') end it 'does not tell current value' do expect(value.is_to_s('not_at_all_secret')).not_to include('not_at_all_secret') end it 'tells redaction warning in place of new value' do expect(value.should_to_s('not_at_all_secret')).to eq('[redacted sensitive information]') end it 'does not tell new value' do expect(value.should_to_s('not_at_all_secret')).not_to include('not_at_all_secret') end end end end end puppetlabs-inifile-2.2.1/spec/unit/puppet/util0040755005276200011600000000000013265372213016430 5ustar00puppetlabs-inifile-2.2.1/spec/unit/puppet/util/external_iterator_spec.rb0100644005276200011600000000167513261374561023613 0ustar00require 'spec_helper' require 'puppet/util/external_iterator' describe Puppet::Util::ExternalIterator do subject_class = nil expected_values = nil before(:each) do subject_class = described_class.new(%w[a b c]) expected_values = [['a', 0], ['b', 1], ['c', 2]] end context '#next' do it 'iterates over the items' do expected_values.each do |expected_pair| expect(subject_class.next).to eq(expected_pair) end end end context '#peek' do it 'returns the 0th item repeatedly' do (0..2).each do |_i| expect(subject_class.peek).to eq(expected_values[0]) end end it 'does not advance the iterator, but should reflect calls to #next' do expected_values.each do |expected_pair| expect(subject_class.peek).to eq(expected_pair) expect(subject_class.peek).to eq(expected_pair) expect(subject_class.next).to eq(expected_pair) end end end end puppetlabs-inifile-2.2.1/spec/unit/puppet/util/ini_file_spec.rb0100644005276200011600000002346513261374561021637 0ustar00require 'spec_helper' require 'stringio' require 'puppet/util/ini_file' require 'pry' describe Puppet::Util::IniFile do subject(:ini_sub) { described_class.new('/my/ini/file/path') } before :each do allow(File).to receive(:file?).with('/my/ini/file/path') { true } allow(described_class).to receive(:readlines).once.with('/my/ini/file/path') do sample_content end end context 'when parsing a file' do let(:sample_content) do 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") end it 'parses the correct number of sections' do # there is always a "global" section, so our count should be 3. expect(ini_sub.section_names.length).to eq(3) end it 'parses the correct section_names' do # there should always be a "global" section named "" at the beginning of the list expect(ini_sub.section_names).to eq(['', 'section1', 'section2']) end it 'exposes settings for sections #section1' do expect(ini_sub.get_settings('section1')).to eq('bar' => 'barvalue', 'baz' => '', 'foo' => 'foovalue') end it 'exposes settings for sections #section2' do expect(ini_sub.get_settings('section2')).to eq('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) do template = <<-EOS [section1] ; This is a comment foo=foovalue EOS template.split("\n") end it 'parses the correct number of sections' do # there is always a "global" section, so our count should be 2. expect(ini_sub.section_names.length).to eq(2) end it 'parses the correct section_names' do # there should always be a "global" section named "" at the beginning of the list expect(ini_sub.section_names).to eq(['', 'section1']) end it 'exposes settings for sections' do expect(ini_sub.get_value('section1', 'foo')).to eq('foovalue') end end context "when parsing a file with a 'global' section" do let(:sample_content) do template = <<-EOS foo = bar [section1] ; This is a comment foo=foovalue EOS template.split("\n") end it 'parses the correct number of sections' do # there is always a "global" section, so our count should be 2. expect(ini_sub.section_names.length).to eq(2) end it 'parses the correct section_names' do # there should always be a "global" section named "" at the beginning of the list expect(ini_sub.section_names).to eq(['', 'section1']) end it 'exposes settings for sections #bar' do expect(ini_sub.get_value('', 'foo')).to eq('bar') end it 'exposes settings for sections #foovalue' do expect(ini_sub.get_value('section1', 'foo')).to eq('foovalue') end end context 'when updating a file with existing empty values' do let(:sample_content) do template = <<-EOS [section1] foo= #bar= #xyzzy['thing1']['thing2']='xyzzyvalue' EOS template.split("\n") end # rubocop:disable RSpec/ExpectInHook before :each do expect(ini_sub.get_value('section1', 'far')).to eq(nil) expect(ini_sub.get_value('section1', 'bar')).to eq(nil) expect(ini_sub.get_value('section1', "xyzzy['thing1']['thing2']")).to eq(nil) end # rubocop:enable RSpec/ExpectInHook it 'properlies update uncommented values' do ini_sub.set_value('section1', 'foo', ' = ', 'foovalue') expect(ini_sub.get_value('section1', 'foo')).to eq('foovalue') end it 'properlies update uncommented values without separator' do ini_sub.set_value('section1', 'foo', 'foovalue') expect(ini_sub.get_value('section1', 'foo')).to eq('foovalue') end it 'properlies update commented value' do ini_sub.set_value('section1', 'bar', ' = ', 'barvalue') expect(ini_sub.get_value('section1', 'bar')).to eq('barvalue') end it 'properlies update commented values' do ini_sub.set_value('section1', "xyzzy['thing1']['thing2']", ' = ', 'xyzzyvalue') expect(ini_sub.get_value('section1', "xyzzy['thing1']['thing2']")).to eq('xyzzyvalue') end it 'properlies update commented value without separator' do ini_sub.set_value('section1', 'bar', 'barvalue') expect(ini_sub.get_value('section1', 'bar')).to eq('barvalue') end it 'properlies update commented values without separator' do ini_sub.set_value('section1', "xyzzy['thing1']['thing2']", 'xyzzyvalue') expect(ini_sub.get_value('section1', "xyzzy['thing1']['thing2']")).to eq('xyzzyvalue') end it 'properlies add new empty values' do ini_sub.set_value('section1', 'baz', ' = ', 'bazvalue') expect(ini_sub.get_value('section1', 'baz')).to eq('bazvalue') end it 'adds new empty values without separator' do ini_sub.set_value('section1', 'baz', 'bazvalue') expect(ini_sub.get_value('section1', 'baz')).to eq('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 'parses the sections' do expect(ini_sub.section_names).to 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 'parses the correct section_names' do expect(ini_sub.section_names).to 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 'parses the correct section_names' do expect(ini_sub.section_names).to 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 'exposes settings for sections #print' do expect(ini_sub.get_value('khotkeys', '{5465e8c7-d608-4493-a48f-b99d99fdb508}')).to eq('Print,none,PrintScreen') end it 'exposes settings for sections #search' do expect(ini_sub.get_value('khotkeys', '{d03619b6-9b3c-48cc-9d9c-a2aadb485550}')).to eq('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 'exposes settings for sections #A' do expect(ini_sub.get_value('Drive names', 'A:')).to eq '5.25" Floppy' end it 'exposes settings for sections #B' do expect(ini_sub.get_value('Drive names', 'B:')).to eq '3.5" Floppy' end it 'exposes settings for sections #C' do expect(ini_sub.get_value('Drive names', 'C:')).to 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 'exposes settings for sections #log' do expect(ini_sub.get_value('global', 'log file')).to eq '/var/log/samba/log.%m' end it 'exposes settings for sections #kerberos' do expect(ini_sub.get_value('global', 'kerberos method')).to eq 'system keytab' end it 'exposes settings for sections #passdb' do expect(ini_sub.get_value('global', 'passdb backend')).to eq 'tdbsam' end it 'exposes settings for sections #security' do expect(ini_sub.get_value('global', 'security')).to eq 'ads' end end end puppetlabs-inifile-2.2.1/spec/unit/puppet/util/setting_value_spec.rb0100644005276200011600000001101213261374561022713 0ustar00require '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"'.freeze let(:setting_value) { described_class.new(INIT_VALUE_SPACE, ' ') } it 'gets the original value' do expect(setting_value.get_value).to eq(INIT_VALUE_SPACE) end it 'gets the correct value' do expect(setting_value.get_subsetting_value('-Xmx')).to eq('192m') end it 'adds a new value #correct' do setting_value.add_subsetting('-Xms', '256m') expect(setting_value.get_subsetting_value('-Xms')).to eq('256m') end it 'adds a new value #original' do setting_value.add_subsetting('-Xms', '256m') expect(setting_value.get_value).to eq(INIT_VALUE_SPACE[0, INIT_VALUE_SPACE.length - 1] + ' -Xms256m"') end it 'changes existing value' do setting_value.add_subsetting('-Xmx', '512m') expect(setting_value.get_subsetting_value('-Xmx')).to eq('512m') end it 'removes existing value' do setting_value.remove_subsetting('-Xmx') expect(setting_value.get_subsetting_value('-Xmx')).to eq(nil) end end describe 'comma subsetting separator' do INIT_VALUE_COMMA = '"-Xmx192m,-XX:+HeapDumpOnOutOfMemoryError,-XX:HeapDumpPath=/var/log/pe-puppetdb/puppetdb-oom.hprof"'.freeze let(:setting_value) { described_class.new(INIT_VALUE_COMMA, ',') } it 'gets the original value' do expect(setting_value.get_value).to eq(INIT_VALUE_COMMA) end it 'gets the correct value' do expect(setting_value.get_subsetting_value('-Xmx')).to eq('192m') end it 'adds a new value #actual' do setting_value.add_subsetting('-Xms', '256m') expect(setting_value.get_subsetting_value('-Xms')).to eq('256m') end it 'adds a new value #original' do setting_value.add_subsetting('-Xms', '256m') expect(setting_value.get_value).to eq(INIT_VALUE_COMMA[0, INIT_VALUE_COMMA.length - 1] + ',-Xms256m"') end it 'changes existing value' do setting_value.add_subsetting('-Xmx', '512m') expect(setting_value.get_subsetting_value('-Xmx')).to eq('512m') end it 'removes existing value' do setting_value.remove_subsetting('-Xmx') expect(setting_value.get_subsetting_value('-Xmx')).to eq(nil) end end describe 'quote_char parameter' do QUOTE_CHAR = '"'.freeze INIT_VALUE_UNQUOTED = '-Xmx192m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/pe-puppetdb/puppetdb-oom.hprof'.freeze it 'gets quoted empty string if original value was empty' do setting_value = described_class.new(nil, ' ', QUOTE_CHAR) expect(setting_value.get_value).to eq(QUOTE_CHAR * 2) end it 'quotes the setting when adding a value #actual' do setting_value = described_class.new(INIT_VALUE_UNQUOTED, ' ', QUOTE_CHAR) setting_value.add_subsetting('-Xms', '256m') expect(setting_value.get_subsetting_value('-Xms')).to eq('256m') end it 'quotes the setting when adding a value #original' do setting_value = described_class.new(INIT_VALUE_UNQUOTED, ' ', QUOTE_CHAR) setting_value.add_subsetting('-Xms', '256m') expect(setting_value.get_value).to eq(QUOTE_CHAR + INIT_VALUE_UNQUOTED + ' -Xms256m' + QUOTE_CHAR) end it 'quotes the setting when changing an existing value #value' do setting_value = described_class.new(INIT_VALUE_UNQUOTED, ' ', QUOTE_CHAR) setting_value.add_subsetting('-Xmx', '512m') expect(setting_value.get_subsetting_value('-Xmx')).to eq('512m') end it 'quotes the setting when changing an existing value #quotes' do setting_value = described_class.new(INIT_VALUE_UNQUOTED, ' ', QUOTE_CHAR) setting_value.add_subsetting('-Xmx', '512m') expect(setting_value.get_value).to match(%r{^#{Regexp.quote(QUOTE_CHAR)}.*#{Regexp.quote(QUOTE_CHAR)}$}) end it 'quotes the setting when removing an existing value #value' do setting_value = described_class.new(INIT_VALUE_UNQUOTED, ' ', QUOTE_CHAR) setting_value.remove_subsetting('-Xmx') expect(setting_value.get_subsetting_value('-Xmx')).to eq(nil) end end it 'quotes the setting when removing an existing value #quotes' do setting_value = described_class.new(INIT_VALUE_UNQUOTED, ' ', QUOTE_CHAR) setting_value.remove_subsetting('-Xmx') expect(setting_value.get_value).to match(%r{^#{Regexp.quote(QUOTE_CHAR)}.*#{Regexp.quote(QUOTE_CHAR)}$}) end end