diff --git a/Puppetfile b/Puppetfile index 2b54e4a6c..f71c954d4 100644 --- a/Puppetfile +++ b/Puppetfile @@ -55,7 +55,7 @@ mod 'horizon', :git => 'https://github.com/stackforge/puppet-horizon.git' mod 'inifile', - :commit => 'fe9b0d5229ea37179a08c4b49239da9bc950acd1', + :commit => '6b399c2bc6b34fd01c704dd5836c61935cf9e4f1', :git => 'https://github.com/puppetlabs/puppetlabs-inifile.git' mod 'ipa', diff --git a/inifile/.fixtures.yml b/inifile/.fixtures.yml index f74b0177c..db98538e8 100644 --- a/inifile/.fixtures.yml +++ b/inifile/.fixtures.yml @@ -1,3 +1,3 @@ fixtures: symlinks: - inifile: '#{source_dir}' + inifile: "#{source_dir}" diff --git a/inifile/.gitignore b/inifile/.gitignore index f9d3de20b..b5b7a00d6 100644 --- a/inifile/.gitignore +++ b/inifile/.gitignore @@ -1,4 +1,7 @@ -spec/fixtures/modules/inifile -spec/fixtures/manifests/site.pp -spec/fixtures/tmp/* +pkg/ Gemfile.lock +vendor/ +spec/fixtures/ +.vagrant/ +.bundle/ +coverage/ diff --git a/inifile/.sync.yml b/inifile/.sync.yml new file mode 100644 index 000000000..66a03c649 --- /dev/null +++ b/inifile/.sync.yml @@ -0,0 +1,3 @@ +--- +spec/spec_helper.rb: + unmanaged: true diff --git a/inifile/.travis.yml b/inifile/.travis.yml index eae801faa..6cf8b0044 100644 --- a/inifile/.travis.yml +++ b/inifile/.travis.yml @@ -1,40 +1,17 @@ --- -branches: - only: - - master language: ruby -bundler_args: --without development -script: bundle exec rake spec SPEC_OPTS='--format documentation' -after_success: - - git clone -q git://github.com/puppetlabs/ghpublisher.git .forge-releng - - .forge-releng/publish -rvm: - - 1.8.7 - - 1.9.3 - - 2.0.0 -env: - matrix: - - PUPPET_GEM_VERSION="~> 2.7.0" - - PUPPET_GEM_VERSION="~> 3.0.0" - - PUPPET_GEM_VERSION="~> 3.1.0" - - PUPPET_GEM_VERSION="~> 3.2.0" - global: - - PUBLISHER_LOGIN=puppetlabs - - secure: |- - mEqZt84gUpTwozeWT4ra2NIQID4CHkvcDcL/8+ItnS3ahbZ4EOj4NLnEWcNt\nxtOjs6pxn - GVND1/gy/1+7w81DpXpJQ6CGloEwP58x86icvrgp8E+ZXeAoYe4\nfqtSE190FMq5FWaPyx - wZisaT2OcrpeqvBPQnaGUg4uz/H3djgUo= +bundler_args: --without system_tests +script: "bundle exec rake validate && bundle exec rake lint && bundle exec rake spec SPEC_OPTS='--format documentation'" matrix: - exclude: - - rvm: 1.9.3 - env: PUPPET_GEM_VERSION="~> 2.7.0" - - rvm: 2.0.0 - env: PUPPET_GEM_VERSION="~> 2.7.0" - - rvm: 2.0.0 - env: PUPPET_GEM_VERSION="~> 3.0.0" - - rvm: 2.0.0 - env: PUPPET_GEM_VERSION="~> 3.1.0" - - rvm: 1.8.7 - env: PUPPET_GEM_VERSION="~> 3.2.0" + fast_finish: true + include: + - rvm: 1.8.7 + env: PUPPET_GEM_VERSION="~> 2.7.0" FACTER_GEM_VERSION="~> 1.6.0" + - rvm: 1.8.7 + env: PUPPET_GEM_VERSION="~> 2.7.0" FACTER_GEM_VERSION="~> 1.7.0" + - rvm: 1.9.3 + env: PUPPET_GEM_VERSION="~> 3.0" + - rvm: 2.0.0 + env: PUPPET_GEM_VERSION="~> 3.0" notifications: email: false diff --git a/inifile/CHANGELOG b/inifile/CHANGELOG deleted file mode 100644 index 54a245f98..000000000 --- a/inifile/CHANGELOG +++ /dev/null @@ -1,89 +0,0 @@ -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) diff --git a/inifile/CHANGELOG.md b/inifile/CHANGELOG.md new file mode 100644 index 000000000..ab0263868 --- /dev/null +++ b/inifile/CHANGELOG.md @@ -0,0 +1,194 @@ +##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) diff --git a/inifile/CONTRIBUTING.md b/inifile/CONTRIBUTING.md new file mode 100644 index 000000000..f1cbde4bb --- /dev/null +++ b/inifile/CONTRIBUTING.md @@ -0,0 +1,220 @@ +Checklist (and a short version for the impatient) +================================================= + + * Commits: + + - Make commits of logical units. + + - Check for unnecessary whitespace with "git diff --check" before + committing. + + - Commit using Unix line endings (check the settings around "crlf" in + git-config(1)). + + - Do not check in commented out code or unneeded files. + + - The first line of the commit message should be a short + description (50 characters is the soft limit, excluding ticket + number(s)), and should skip the full stop. + + - Associate the issue in the message. The first line should include + the issue number in the form "(#XXXX) Rest of message". + + - The body should provide a meaningful commit message, which: + + - uses the imperative, present tense: "change", not "changed" or + "changes". + + - includes motivation for the change, and contrasts its + implementation with the previous behavior. + + - Make sure that you have tests for the bug you are fixing, or + feature you are adding. + + - Make sure the test suites passes after your commit: + `bundle exec rspec spec/acceptance` More information on [testing](#Testing) below + + - When introducing a new feature, make sure it is properly + documented in the README.md + + * Submission: + + * Pre-requisites: + + - Make sure you have a [GitHub account](https://github.com/join) + + - [Create a ticket](https://tickets.puppetlabs.com/secure/CreateIssue!default.jspa), or [watch the ticket](https://tickets.puppetlabs.com/browse/) you are patching for. + + * Preferred method: + + - Fork the repository on GitHub. + + - Push your changes to a topic branch in your fork of the + repository. (the format ticket/1234-short_description_of_change is + usually preferred for this project). + + - Submit a pull request to the repository in the puppetlabs + organization. + +The long version +================ + + 1. Make separate commits for logically separate changes. + + Please break your commits down into logically consistent units + which include new or changed tests relevant to the rest of the + change. The goal of doing this is to make the diff easier to + read for whoever is reviewing your code. In general, the easier + your diff is to read, the more likely someone will be happy to + review it and get it into the code base. + + If you are going to refactor a piece of code, please do so as a + separate commit from your feature or bug fix changes. + + We also really appreciate changes that include tests to make + sure the bug is not re-introduced, and that the feature is not + accidentally broken. + + Describe the technical detail of the change(s). If your + description starts to get too long, that is a good sign that you + probably need to split up your commit into more finely grained + pieces. + + Commits which plainly describe the things which help + reviewers check the patch and future developers understand the + code are much more likely to be merged in with a minimum of + bike-shedding or requested changes. Ideally, the commit message + would include information, and be in a form suitable for + inclusion in the release notes for the version of Puppet that + includes them. + + Please also check that you are not introducing any trailing + whitespace or other "whitespace errors". You can do this by + running "git diff --check" on your changes before you commit. + + 2. Sending your patches + + To submit your changes via a GitHub pull request, we _highly_ + recommend that you have them on a topic branch, instead of + directly on "master". + It makes things much easier to keep track of, especially if + you decide to work on another thing before your first change + is merged in. + + GitHub has some pretty good + [general documentation](http://help.github.com/) on using + their site. They also have documentation on + [creating pull requests](http://help.github.com/send-pull-requests/). + + In general, after pushing your topic branch up to your + repository on GitHub, you can switch to the branch in the + GitHub UI and click "Pull Request" towards the top of the page + in order to open a pull request. + + + 3. Update the related GitHub issue. + + If there is a GitHub issue associated with the change you + submitted, then you should update the ticket to include the + location of your branch, along with any other commentary you + may wish to make. + +Testing +======= + +Getting Started +--------------- + +Our puppet modules provide [`Gemfile`](./Gemfile)s which can tell a ruby +package manager such as [bundler](http://bundler.io/) what Ruby packages, +or Gems, are required to build, develop, and test this software. + +Please make sure you have [bundler installed](http://bundler.io/#getting-started) +on your system, then use it to install all dependencies needed for this project, +by running + +```shell +% bundle install +Fetching gem metadata from https://rubygems.org/........ +Fetching gem metadata from https://rubygems.org/.. +Using rake (10.1.0) +Using builder (3.2.2) +-- 8><-- many more --><8 -- +Using rspec-system-puppet (2.2.0) +Using serverspec (0.6.3) +Using rspec-system-serverspec (1.0.0) +Using bundler (1.3.5) +Your bundle is complete! +Use `bundle show [gemname]` to see where a bundled gem is installed. +``` + +NOTE some systems may require you to run this command with sudo. + +If you already have those gems installed, make sure they are up-to-date: + +```shell +% bundle update +``` + +With all dependencies in place and up-to-date we can now run the tests: + +```shell +% rake spec +``` + +This will execute all the [rspec tests](http://rspec-puppet.com/) tests +under [spec/defines](./spec/defines), [spec/classes](./spec/classes), +and so on. rspec tests may have the same kind of dependencies as the +module they are testing. While the module defines in its [Modulefile](./Modulefile), +rspec tests define them in [.fixtures.yml](./fixtures.yml). + +Some puppet modules also come with [beaker](https://github.com/puppetlabs/beaker) +tests. These tests spin up a virtual machine under +[VirtualBox](https://www.virtualbox.org/)) with, controlling it with +[Vagrant](http://www.vagrantup.com/) to actually simulate scripted test +scenarios. In order to run these, you will need both of those tools +installed on your system. + +You can run them by issuing the following command + +```shell +% rake spec_clean +% rspec spec/acceptance +``` + +This will now download a pre-fabricated image configured in the [default node-set](./spec/acceptance/nodesets/default.yml), +install puppet, copy this module and install its dependencies per [spec/spec_helper_acceptance.rb](./spec/spec_helper_acceptance.rb) +and then run all the tests under [spec/acceptance](./spec/acceptance). + +Writing Tests +------------- + +XXX getting started writing tests. + +If you have commit access to the repository +=========================================== + +Even if you have commit access to the repository, you will still need to +go through the process above, and have someone else review and merge +in your changes. The rule is that all changes must be reviewed by a +developer on the project (that did not write the code) to ensure that +all changes go through a code review process. + +Having someone other than the author of the topic branch recorded as +performing the merge is the record that they performed the code +review. + + +Additional Resources +==================== + +* [Getting additional help](http://puppetlabs.com/community/get-help) + +* [Writing tests](http://projects.puppetlabs.com/projects/puppet/wiki/Development_Writing_Tests) + +* [Patchwork](https://patchwork.puppetlabs.com) + +* [General GitHub documentation](http://help.github.com/) + +* [GitHub pull request documentation](http://help.github.com/send-pull-requests/) + diff --git a/inifile/Gemfile b/inifile/Gemfile index 72e8342df..12fd363ea 100644 --- a/inifile/Gemfile +++ b/inifile/Gemfile @@ -1,11 +1,24 @@ -source 'https://rubygems.org' +source ENV['GEM_SOURCE'] || "https://rubygems.org" -group :development, :test do - gem 'rake', :require => false - gem 'rspec-puppet', :require => false - gem 'puppetlabs_spec_helper', :require => false - gem 'simplecov', :require => false - gem 'pry', :require => false +group :development, :unit_tests do + gem 'rake', :require => false + gem 'rspec-puppet', :require => false + gem 'puppetlabs_spec_helper', :require => false + gem 'puppet-lint', :require => false + gem 'simplecov', :require => false + gem 'puppet_facts', :require => false + gem 'json', :require => false +end + +group :system_tests do + gem 'beaker-rspec', :require => false + gem 'serverspec', :require => false +end + +if facterversion = ENV['FACTER_GEM_VERSION'] + gem 'facter', facterversion, :require => false +else + gem 'facter', :require => false end if puppetversion = ENV['PUPPET_GEM_VERSION'] diff --git a/inifile/Modulefile b/inifile/Modulefile deleted file mode 100644 index 963f950c1..000000000 --- a/inifile/Modulefile +++ /dev/null @@ -1,8 +0,0 @@ -name 'puppetlabs-inifile' -version '1.0.0' -source 'git://github.com/puppetlabs/puppetlabs-inifile.git' -author 'Puppetlabs' -description 'Resource types for managing settings in INI files' -summary 'Resource types for managing settings in INI files' -license 'Apache' -project_page 'https://github.com/puppetlabs/puppetlabs-inifile' diff --git a/inifile/README.markdown b/inifile/README.markdown index a2e1652ab..2a2f8f87a 100644 --- a/inifile/README.markdown +++ b/inifile/README.markdown @@ -1,107 +1,226 @@ -[![Build Status](https://travis-ci.org/puppetlabs/puppetlabs-inifile.png?branch=master)](https://travis-ci.org/cprice-puppet/puppetlabs-inifile) -# INI-file module # -This module provides resource types for use in managing INI-style configuration -files. The main resource type is `ini_setting`, which is used to manage an -individual setting in an INI file. Here's an example usage: +#INI file - ini_setting { "sample setting": - path => '/tmp/foo.ini', - section => 'foo', - setting => 'foosetting', - value => 'FOO!', - ensure => present, - } +[![Build Status](https://travis-ci.org/puppetlabs/puppetlabs-inifile.png?branch=master)](https://travis-ci.org/puppetlabs/puppetlabs-inifile) -A supplementary resource type is `ini_subsetting`, which is used to manage -settings that consist of several arguments such as +####Table of Contents - JAVA_ARGS="-Xmx192m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/pe-puppetdb/puppetdb-oom.hprof " +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) + * [Setup requirements](#setup-requirements) + * [Beginning with inifile](#beginning-with-inifile) +4. [Usage - Configuration options and additional functionality](#usage) +5. [Reference - An under-the-hood peek at what the module is doing and how](#reference) +5. [Limitations - OS compatibility, etc.](#limitations) +6. [Development - Guide for contributing to the module](#development) - ini_subsetting {'sample subsetting': - ensure => present, - section => '', - key_val_separator => '=', - path => '/etc/default/pe-puppetdb', - setting => 'JAVA_ARGS', - subsetting => '-Xmx', - value => '512m', - } +##Overview -## implementing child providers: +This module adds resource types to manage settings in INI-style configuration files. +##Module Description -The ini_setting class can be overridden by child providers in order to implement the management of ini settings for a specific configuration file. +The inifile module adds two resource types so that you can use Puppet to manage settings and subsettings in INI-style configuration files. -In order to implement this, you will need to specify your own Type (as shown below). This type needs to implement a namevar (name), and a property called value: +This module tries hard not to manipulate your file any more than it needs to. In most cases, it should leave the original whitespace, comments, ordering, etc. intact. +###Noteworthy module features include: - example: - - #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 be defined.' - munge do |v| - v.to_s.strip - end - end + * Supports comments starting with either '#' or ';'. + * Supports either whitespace or no whitespace around '='. + * Adds any missing sections to the INI file. + +##Setup + +##Beginning with inifile + +To manage an INI file, add the resource type `ini_setting` or `ini_subsetting` to a class. + +##Usage + +Manage individual settings in INI files by adding the `ini_setting` resource type to a class. For example: + +``` +ini_setting { "sample setting": + ensure => present, + path => '/tmp/foo.ini', + section => 'foo', + setting => 'foosetting', + value => 'FOO!', +} +``` + +To control multiple values in a setting, use `ini_subsetting`. For example: + +``` +JAVA_ARGS="-Xmx192m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/pe-puppetdb/puppetdb-oom.hprof " + +ini_subsetting {'sample subsetting': + ensure => present, + section => '', + key_val_separator => '=', + path => '/etc/default/pe-puppetdb', + setting => 'JAVA_ARGS', + subsetting => '-Xmx', + value => '512m', +} +``` + +###Implementing child providers: + +You can set up custom child providers that inherit the `ini_setting` provider. This allows you to implement custom resources to manage INI settings for specific configuration files without copying all the code or writing your own code from scratch. This also allows resource purging to be used. + +To implement child providers, you'll need to specify your own type. This type needs to implement a namevar (name) and a property called value: + +For example: + +``` +#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 be defined.' + munge do |v| + v.to_s.strip end + end +end +``` -This type also must have a provider that utilizes the ini_setting provider as its parent: - - example: - - # 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 +This type must also have a provider that uses the `ini_setting` provider as its parent. For example: +``` +# my_module/lib/puppet/provider/glance_api_config/ini_setting.rb +Puppet::Type.type(:glance_api_config).provide( + :ini_setting, + # set ini_setting as the parent provider + :parent => Puppet::Type.type(:ini_setting).provider(:ruby) +) do + # implement section as the first part of the namevar + def section + resource[:name].split('/', 2).first + end + def setting + # implement setting as the second part of the namevar + resource[:name].split('/', 2).last + end + # hard code the file path (this allows purging) + def self.file_path + '/etc/glance/glance-api.conf' + end +end +``` -Now, the individual settings of the /etc/glance/glance-api.conf file can be managed as individual resources: +Now the individual settings of the /etc/glance/glance-api.conf file can be managed as individual resources: - glance_api_config { 'HEADER/important_config': - value => 'secret_value', - } +``` +glance_api_config { 'HEADER/important_config': + value => 'secret_value', +} +``` -Provided that self.file_path has been implemented, you can purge with the following puppet syntax: +If the self.file_path has been implemented, you can purge with the following Puppet syntax: - resources { 'glance_api_config' - purge => true, - } +``` +resources { 'glance_api_config' + purge => true, +} +``` -If the above code is added, then the resulting configured file will only contain lines implemented as Puppet resources +If the above code is added, the resulting configured file will contain only lines implemented as Puppet resources. + +##Reference + +###Type: ini_setting + +#### Parameters + +* `ensure`: Ensures that the resource is present. Valid values are 'present', 'absent'. + +* `key_val_separator`: The separator string to use between each setting name and value. Defaults to ' = ', but you could use this to override the default (e.g., whether or not the separator should include whitespace). + +* `name`: An arbitrary name used as the identity of the resource. + +* `path`: The INI file in which Puppet ensures the specified setting. + +* `provider`: The specific backend to use for this `ini_setting` resource. You will seldom need to specify this --- Puppet usually discovers the appropriate provider for your platform. The only available provider for `ini_setting` is ruby. + +* `section`: The name of the INI file section in which the setting should be defined. Add a global section --- settings that appear at the beginning of the file, before any named sections --- by specifying a section name of "". + +* `setting`: The name of the INI file setting to be defined. + +* `value`: The value of the INI file setting to be defined. + +###Type: ini_subsetting + +#### Parameters + +* `ensure`: Ensures that the resource is present. Valid values are 'present', 'absent'. + +* `key_val_separator`: The separator string to use between each setting name and value. Defaults to ' = ', but you could use this to override the default (e.g., whether or not the separator should include whitespace). + +* `name`: An arbitrary name used as the identity of the resource. + +* `path`: The INI file in which Puppet ensures the specified setting. + +* `provider`: The specific backend to use for this `ini_subsetting` resource. You will seldom need to specify this --- Puppet usually discovers the appropriate provider for your platform. The only available provider for `ini_subsetting` is ruby. + +* `quote_char`: The character used to quote the entire value of the setting. Valid values are '', '"', and "'". Defaults to ''. + +* `section`: The name of the INI file section in which the setting should be defined. Add a global section --- settings that appear at the beginning of the file, before any named sections --- by specifying a section name of "". + +* `setting`: The name of the INI file setting to be defined. + +* `subsetting`: The name of the INI file subsetting to be defined. + +* `subsetting_separator`: The separator string used between subsettings. Defaults to " ". + +* `value`: The value of the INI file subsetting to be defined. + +##Limitations + +This module is officially [supported](https://forge.puppetlabs.com/supported) on : + +* Red Hat Enterprise Linux (RHEL) 5, 6, 7 +* CentOS 5, 6, 7 +* Oracle Linux 5, 6, 7 +* Scientific Linux 5, 6, 7 +* SLES 11 SP1 or greater +* Debian 6, 7 +* Ubuntu 10.04 LTS, 12.04 LTS, 14.04 LTS +* Solaris 10, 11 +* Windows Server 2003/2008 R2, 2012/2012 R2 +* AIX 5.3, 6.1, 7.1 + +This module has also been tested, but is not officially supported, on: + +* Red Hat Enterprise Linux (RHEL) 4 +* Windows 7 +* Mac OSX 10.9 (Mavericks) + +### Agent run failure with Puppet Enterprise + +As of Puppet Enterprise 3.3, agent runs on master fail if you are using an older, manually installed version of inifile. To solve this problem, upgrade your inifile module to version 1.1.0 or later. + +##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. + +You can read the complete module contribution guide in [CONTRIBUTING.md](./CONTRIBUTING.md) + +##Contributors + +The list of contributors can be found at: [https://github.com/puppetlabs/puppetlabs-inifile/graphs/contributors](https://github.com/puppetlabs/puppetlabs-inifile/graphs/contributors). -## A few noteworthy features: - * The module tries *hard* not to manipulate your file any more than it needs to. - In most cases, it should leave the original whitespace, comments, ordering, - etc. perfectly intact. - * Supports comments starting with either '#' or ';'. - * Will add missing sections if they don't exist. - * Supports a "global" section (settings that go at the beginning of the file, - before any named sections) by specifying a section name of "". diff --git a/inifile/Rakefile b/inifile/Rakefile index cd3d37995..e3be95b0b 100644 --- a/inifile/Rakefile +++ b/inifile/Rakefile @@ -1 +1,10 @@ require 'puppetlabs_spec_helper/rake_tasks' +require 'puppet-lint/tasks/puppet-lint' + +PuppetLint.configuration.fail_on_warnings +PuppetLint.configuration.send('relative') +PuppetLint.configuration.send('disable_80chars') +PuppetLint.configuration.send('disable_class_inherits_from_params_class') +PuppetLint.configuration.send('disable_documentation') +PuppetLint.configuration.send('disable_single_quote_string_with_variables') +PuppetLint.configuration.ignore_paths = ["spec/**/*.pp", "pkg/**/*.pp"] diff --git a/inifile/lib/puppet/provider/ini_setting/ruby.rb b/inifile/lib/puppet/provider/ini_setting/ruby.rb index 1b2bc80ee..7831a4fb0 100644 --- a/inifile/lib/puppet/provider/ini_setting/ruby.rb +++ b/inifile/lib/puppet/provider/ini_setting/ruby.rb @@ -38,7 +38,7 @@ def self.namevar(section_name, setting) end def exists? - ini_file.get_value(section, setting) + !ini_file.get_value(section, setting).nil? end def create diff --git a/inifile/lib/puppet/provider/ini_subsetting/ruby.rb b/inifile/lib/puppet/provider/ini_subsetting/ruby.rb index 49c0e49ba..764124dda 100644 --- a/inifile/lib/puppet/provider/ini_subsetting/ruby.rb +++ b/inifile/lib/puppet/provider/ini_subsetting/ruby.rb @@ -57,14 +57,17 @@ def separator resource[:key_val_separator] || '=' end + def quote_char + resource[:quote_char] + end + private def ini_file @ini_file ||= Puppet::Util::IniFile.new(file_path, separator) end - private def setting_value - @setting_value ||= Puppet::Util::SettingValue.new(ini_file.get_value(section, setting), subsetting_separator) + @setting_value ||= Puppet::Util::SettingValue.new(ini_file.get_value(section, setting), subsetting_separator, quote_char) end end diff --git a/inifile/lib/puppet/type/ini_subsetting.rb b/inifile/lib/puppet/type/ini_subsetting.rb index dd146c291..847e31797 100644 --- a/inifile/lib/puppet/type/ini_subsetting.rb +++ b/inifile/lib/puppet/type/ini_subsetting.rb @@ -48,6 +48,18 @@ end end + newparam(:quote_char) do + desc 'The character used to quote the entire value of the setting. ' + + %q{Valid values are '', '"' and "'". Defaults to ''.} + defaultto('') + + validate do |value| + unless value =~ /^["']?$/ + raise Puppet::Error, %q{:quote_char valid values are '', '"' and "'"} + end + end + end + newproperty(:value) do desc 'The value of the subsetting to be defined.' end diff --git a/inifile/lib/puppet/util/ini_file.rb b/inifile/lib/puppet/util/ini_file.rb index 53bed2d5f..a5cefa763 100644 --- a/inifile/lib/puppet/util/ini_file.rb +++ b/inifile/lib/puppet/util/ini_file.rb @@ -5,9 +5,9 @@ module Puppet module Util class IniFile - @@SECTION_REGEX = /^\s*\[([\w\d\.\\\/\-\:]+)\]\s*$/ - @@SETTING_REGEX = /^(\s*)([\w\d\.\\\/\-\s]*[\w\d\.\\\/\-])([ \t]*=[ \t]*)([\S\s]*?)\s*$/ - @@COMMENTED_SETTING_REGEX = /^(\s*)[#;]+(\s*)([\w\d\.\\\/\-]+)([ \t]*=[ \t]*)([\S\s]*?)\s*$/ + @@SECTION_REGEX = /^\s*\[([^\]]*)\]\s*$/ + @@SETTING_REGEX = /^(\s*)([^\s=]*)(\s*=\s*)(.*)\s*$/ + @@COMMENTED_SETTING_REGEX = /^(\s*)[#;]+(\s*)([^\s=]*)(\s*=[ \t]*)(.*)\s*$/ def initialize(path, key_val_separator = ' = ') @path = path diff --git a/inifile/lib/puppet/util/setting_value.rb b/inifile/lib/puppet/util/setting_value.rb index 42cd28ec6..d44330a9a 100644 --- a/inifile/lib/puppet/util/setting_value.rb +++ b/inifile/lib/puppet/util/setting_value.rb @@ -2,19 +2,21 @@ module Puppet module Util class SettingValue - - def initialize(setting_value, subsetting_separator = ' ') + + def initialize(setting_value, subsetting_separator = ' ', default_quote_char = nil) @setting_value = setting_value @subsetting_separator = subsetting_separator - @quote_char = "" + default_quote_char ||= '' if @setting_value unquoted, @quote_char = unquote_setting_value(setting_value) @subsetting_items = unquoted.scan(Regexp.new("(?:(?:[^\\#{@subsetting_separator}]|\\.)+)")) # an item can contain escaped separator @subsetting_items.map! { |item| item.strip } + @quote_char = default_quote_char if @quote_char.empty? else - @subsetting_items = [] + @subsetting_items = [] + @quote_char = default_quote_char end end diff --git a/inifile/metadata.json b/inifile/metadata.json new file mode 100644 index 000000000..9f96ceb01 --- /dev/null +++ b/inifile/metadata.json @@ -0,0 +1,104 @@ +{ + "name": "puppetlabs-inifile", + "version": "1.2.0", + "author": "Puppet Labs", + "summary": "Resource types for managing settings in INI files", + "license": "Apache-2.0", + "source": "https://github.com/puppetlabs/puppetlabs-inifile", + "project_page": "https://github.com/puppetlabs/puppetlabs-inifile", + "issues_url": "https://tickets.puppetlabs.com/browse/MODULES", + "operatingsystem_support": [ + { + "operatingsystem": "RedHat", + "operatingsystemrelease": [ + "5", + "6", + "7" + ] + }, + { + "operatingsystem": "CentOS", + "operatingsystemrelease": [ + "5", + "6", + "7" + ] + }, + { + "operatingsystem": "OracleLinux", + "operatingsystemrelease": [ + "5", + "6", + "7" + ] + }, + { + "operatingsystem": "Scientific", + "operatingsystemrelease": [ + "5", + "6", + "7" + ] + }, + { + "operatingsystem": "SLES", + "operatingsystemrelease": [ + "10 SP4", + "11 SP1", + "12" + ] + }, + { + "operatingsystem": "Debian", + "operatingsystemrelease": [ + "6", + "7" + ] + }, + { + "operatingsystem": "Ubuntu", + "operatingsystemrelease": [ + "10.04", + "12.04", + "14.04" + ] + }, + { + "operatingsystem": "Solaris", + "operatingsystemrelease": [ + "10", + "11" + ] + }, + { + "operatingsystem": "Windows", + "operatingsystemrelease": [ + "Server 2003 R2", + "Server 2008 R2", + "Server 2012", + "Server 2012 R2" + ] + }, + { + "operatingsystem": "AIX", + "operatingsystemrelease": [ + "5.3", + "6.1", + "7.1" + ] + } + ], + "requirements": [ + { + "name": "pe", + "version_requirement": "3.x" + }, + { + "name": "puppet", + "version_requirement": "3.x" + } + ], + "dependencies": [ + + ] +} diff --git a/inifile/spec/acceptance/ini_setting_spec.rb b/inifile/spec/acceptance/ini_setting_spec.rb new file mode 100644 index 000000000..9aad0cc39 --- /dev/null +++ b/inifile/spec/acceptance/ini_setting_spec.rb @@ -0,0 +1,308 @@ +require 'spec_helper_acceptance' + +tmpdir = default.tmpdir('tmp') + +describe 'ini_setting resource' do + after :all do + shell("rm #{tmpdir}/*.ini", :acceptable_exit_codes => [0,1,2]) + end + + shared_examples 'has_content' do |path,pp,content| + before :all do + shell("rm #{path}", :acceptable_exit_codes => [0,1,2]) + end + after :all do + shell("cat #{path}", :acceptable_exit_codes => [0,1,2]) + shell("rm #{path}", :acceptable_exit_codes => [0,1,2]) + end + + it 'applies the manifest twice' do + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => true) + end + + describe file(path) do + it { should be_file } + #XXX Solaris 10 doesn't support multi-line grep + it("should contain #{content}", :unless => fact('osfamily') == 'Solaris') { + should contain(content) + } + end + end + + shared_examples 'has_error' do |path,pp,error| + before :all do + shell("rm #{path}", :acceptable_exit_codes => [0,1,2]) + end + after :all do + shell("cat #{path}", :acceptable_exit_codes => [0,1,2]) + shell("rm #{path}", :acceptable_exit_codes => [0,1,2]) + end + + it 'applies the manifest and gets a failure message' do + expect(apply_manifest(pp, :expect_failures => true).stderr).to match(error) + end + + describe file(path) do + it { should_not be_file } + end + end + + describe 'ensure parameter' do + context '=> present for global and section' do + pp = <<-EOS + ini_setting { 'ensure => present for section': + ensure => present, + path => "#{tmpdir}/ini_setting.ini", + section => 'one', + setting => 'two', + value => 'three', + } + ini_setting { 'ensure => present for global': + ensure => present, + path => "#{tmpdir}/ini_setting.ini", + section => '', + setting => 'four', + value => 'five', + } + EOS + + it 'applies the manifest twice' do + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => true) + end + + describe file("#{tmpdir}/ini_setting.ini") do + it { should be_file } + #XXX Solaris 10 doesn't support multi-line grep + it("should contain four = five\n[one]\ntwo = three", :unless => fact('osfamily') == 'Solaris') { + should contain("four = five\n[one]\ntwo = three") + } + end + end + + context '=> absent for key/value' 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 + + pp = <<-EOS + ini_setting { 'ensure => absent for key/value': + ensure => absent, + path => "#{tmpdir}/ini_setting.ini", + section => 'one', + setting => 'two', + value => 'three', + } + EOS + + it 'applies the manifest twice' do + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => true) + end + + describe file("#{tmpdir}/ini_setting.ini") do + it { should be_file } + it { should contain('four = five') } + it { should contain('[one]') } + it { should_not contain('two = three') } + end + end + + context '=> absent for section', :pending => "cannot ensure absent on a section" 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 section': + ensure => absent, + path => "#{tmpdir}/ini_setting.ini", + section => 'one', + } + EOS + + it 'applies the manifest twice' do + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => true) + end + + describe file("#{tmpdir}/ini_setting.ini") do + it { should be_file } + it { should contain('four = five') } + it { should_not contain('[one]') } + it { should_not contain('two = three') } + end + end + + context '=> absent for global' do + before :all do + if fact('osfamily') == 'Darwin' + shell("echo \"four = five\n[one]\ntwo = three\" > #{tmpdir}/ini_setting.ini") + else + shell("echo -e \"four = five\n[one]\ntwo = three\" > #{tmpdir}/ini_setting.ini") + end + end + after :all do + shell("cat #{tmpdir}/ini_setting.ini", :acceptable_exit_codes => [0,1,2]) + shell("rm #{tmpdir}/ini_setting.ini", :acceptable_exit_codes => [0,1,2]) + end + + pp = <<-EOS + ini_setting { 'ensure => absent for global': + ensure => absent, + path => "#{tmpdir}/ini_setting.ini", + section => '', + setting => 'four', + value => 'five', + } + EOS + + it 'applies the manifest twice' do + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => true) + end + + describe file("#{tmpdir}/ini_setting.ini") do + it { should be_file } + it { should_not contain('four = five') } + it { should contain('[one]') } + it { should contain('two = three') } + end + end + end + + describe 'section, setting, value parameters' do + { + "section => 'test', setting => 'foo', value => 'bar'," => "[test]\nfoo = bar", + "section => 'more', setting => 'baz', value => 'quux'," => "[more]\nbaz = quux", + "section => '', setting => 'top', value => 'level'," => "top = level", + }.each do |parameter_list, content| + context parameter_list do + pp = <<-EOS + ini_setting { "#{parameter_list}": + ensure => present, + path => "#{tmpdir}/ini_setting.ini", + #{parameter_list} + } + EOS + + it_behaves_like 'has_content', "#{tmpdir}/ini_setting.ini", pp, content + end + end + + { + "section => 'test'," => /setting is a required.+value is a required/, + "setting => 'foo', value => 'bar'," => /section is a required/, + "section => 'test', setting => 'foo'," => /value is a required/, + "section => 'test', value => 'bar'," => /setting is a required/, + "value => 'bar'," => /section is a required.+setting is a required/, + "setting => 'foo'," => /section is a required.+value is a required/, + }.each do |parameter_list, error| + context parameter_list, :pending => 'no error checking yet' do + pp = <<-EOS + ini_setting { "#{parameter_list}": + ensure => present, + path => "#{tmpdir}/ini_setting.ini", + #{parameter_list} + } + EOS + + it_behaves_like 'has_error', "#{tmpdir}/ini_setting.ini", pp, error + end + end + end + + describe 'path parameter' do + [ + "#{tmpdir}/one.ini", + "#{tmpdir}/two.ini", + "#{tmpdir}/three.ini", + ].each do |path| + context "path => #{path}" do + pp = <<-EOS + ini_setting { 'path => #{path}': + ensure => present, + section => 'one', + setting => 'two', + value => 'three', + path => '#{path}', + } + EOS + + it_behaves_like 'has_content', path, pp, "[one]\ntwo = three" + end + end + + context "path => foo" do + pp = <<-EOS + ini_setting { 'path => foo': + ensure => present, + section => 'one', + setting => 'two', + value => 'three', + path => 'foo', + } + EOS + + it_behaves_like 'has_error', 'foo', pp, /must be fully qualified/ + end + end + + describe 'key_val_separator parameter' do + { + "" => "two = three", + "key_val_separator => '='," => "two=three", + "key_val_separator => ' = '," => "two = three", + }.each do |parameter, content| + context "with \"#{parameter}\" makes \"#{content}\"" do + pp = <<-EOS + ini_setting { "with #{parameter} makes #{content}": + ensure => present, + section => 'one', + setting => 'two', + value => 'three', + path => "#{tmpdir}/key_val_separator.ini", + #{parameter} + } + EOS + + it_behaves_like 'has_content', "#{tmpdir}/key_val_separator.ini", pp, content + end + end + + { + "key_val_separator => ''," => /must contain exactly one/, + "key_val_separator => ','," => /must contain exactly one/, + "key_val_separator => ' '," => /must contain exactly one/, + "key_val_separator => ' == '," => /must contain exactly one/, + }.each do |parameter, error| + context "with \"#{parameter}\" raises \"#{error}\"" do + pp = <<-EOS + ini_setting { "with #{parameter} raises #{error}": + ensure => present, + section => 'one', + setting => 'two', + value => 'three', + path => "#{tmpdir}/key_val_separator.ini", + #{parameter} + } + EOS + + it_behaves_like 'has_error', "#{tmpdir}/key_val_separator.ini", pp, error + end + end + end +end diff --git a/inifile/spec/acceptance/ini_subsetting_spec.rb b/inifile/spec/acceptance/ini_subsetting_spec.rb new file mode 100644 index 000000000..b801833ad --- /dev/null +++ b/inifile/spec/acceptance/ini_subsetting_spec.rb @@ -0,0 +1,195 @@ +require 'spec_helper_acceptance' + +tmpdir = default.tmpdir('tmp') + +describe 'ini_subsetting resource' do + after :all do + shell("rm #{tmpdir}/*.ini", :acceptable_exit_codes => [0,1,2]) + end + + shared_examples 'has_content' do |path,pp,content| + before :all do + shell("rm #{path}", :acceptable_exit_codes => [0,1,2]) + end + after :all do + shell("cat #{path}", :acceptable_exit_codes => [0,1,2]) + shell("rm #{path}", :acceptable_exit_codes => [0,1,2]) + end + + it 'applies the manifest twice' do + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => true) + end + + describe file(path) do + it { should be_file } + it { should contain(content) } + end + end + + shared_examples 'has_error' do |path,pp,error| + before :all do + shell("rm #{path}", :acceptable_exit_codes => [0,1,2]) + end + after :all do + shell("cat #{path}", :acceptable_exit_codes => [0,1,2]) + shell("rm #{path}", :acceptable_exit_codes => [0,1,2]) + end + + it 'applies the manifest and gets a failure message' do + expect(apply_manifest(pp, :expect_failures => true).stderr).to match(error) + end + + describe file(path) do + it { should_not be_file } + end + end + + describe 'ensure, section, setting, subsetting, & value parameters' do + context '=> present with subsections' do + pp = <<-EOS + ini_subsetting { 'ensure => present for alpha': + ensure => present, + path => "#{tmpdir}/ini_subsetting.ini", + section => 'one', + setting => 'key', + subsetting => 'alpha', + value => 'bet', + } + ini_subsetting { 'ensure => present for beta': + ensure => present, + path => "#{tmpdir}/ini_subsetting.ini", + section => 'one', + setting => 'key', + subsetting => 'beta', + value => 'trons', + } + EOS + + it 'applies the manifest twice' do + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => true) + end + + describe file("#{tmpdir}/ini_subsetting.ini") do + it { should be_file } + #XXX Solaris 10 doesn't support multi-line grep + it("should contain [one]\nkey = alphabet betatrons", :unless => fact('osfamily') == 'Solaris') { + should contain("[one]\nkey = alphabet betatrons") + } + end + end + + context 'ensure => absent' do + before :all do + if fact('osfamily') == 'Darwin' + shell("echo \"[one]\nkey = alphabet betatrons\" > #{tmpdir}/ini_subsetting.ini") + else + shell("echo -e \"[one]\nkey = alphabet betatrons\" > #{tmpdir}/ini_subsetting.ini") + end + end + + pp = <<-EOS + ini_subsetting { 'ensure => absent for subsetting': + ensure => absent, + path => "#{tmpdir}/ini_subsetting.ini", + section => 'one', + setting => 'key', + subsetting => 'alpha', + } + EOS + + it 'applies the manifest twice' do + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => true) + end + + describe file("#{tmpdir}/ini_subsetting.ini") do + it { should be_file } + it { should contain('[one]') } + it { should contain('key = betatrons') } + it { should_not contain('alphabet') } + end + end + end + + describe 'subsetting_separator' do + { + "" => "two = twinethree foobar", + #"subsetting_separator => ''," => "two = twinethreefoobar", # breaks regex + "subsetting_separator => ','," => "two = twinethree,foobar", + "subsetting_separator => ' '," => "two = twinethree foobar", + "subsetting_separator => ' == '," => "two = twinethree == foobar", + "subsetting_separator => '='," => "two = twinethree=foobar", + #"subsetting_separator => '---'," => "two = twinethree---foobar", # breaks regex + }.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", + #{parameter} + } + ini_subsetting { "foobar": + ensure => present, + section => 'one', + setting => 'two', + subsetting => 'foo', + value => 'bar', + path => "#{tmpdir}/subsetting_separator.ini", + #{parameter} + } + EOS + + it_behaves_like 'has_content', "#{tmpdir}/subsetting_separator.ini", pp, content + end + end + end + + describe 'quote_char' do + { + ['-Xmx'] => 'args=""', + ['-Xmx', '256m'] => 'args=-Xmx256m', + ['-Xmx', '512m'] => 'args="-Xmx512m"', + ['-Xms', '256m'] => 'args="-Xmx256m -Xms256m"', + }.each do |parameter, content| + context %Q{with '#{parameter.first}' #{parameter.length > 1 ? '=> \'' << parameter[1] << '\'' : 'absent'} makes '#{content}'} do + path = File.join(tmpdir, 'ini_subsetting.ini') + + before :all do + shell(%Q{echo '[java]\nargs=-Xmx256m' > #{path}}) + end + after :all do + shell("cat #{path}", :acceptable_exit_codes => [0,1,2]) + shell("rm #{path}", :acceptable_exit_codes => [0,1,2]) + end + + pp = <<-EOS + ini_subsetting { '#{parameter.first}': + ensure => #{parameter.length > 1 ? 'present' : 'absent'}, + path => '#{path}', + section => 'java', + setting => 'args', + quote_char => '"', + subsetting => '#{parameter.first}', + value => '#{parameter.length > 1 ? parameter[1] : ''}' + } + EOS + + it 'applies the manifest twice' do + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => true) + end + + describe file("#{tmpdir}/ini_subsetting.ini") do + it { should be_file } + it { should contain(content) } + end + end + end + end +end diff --git a/inifile/spec/acceptance/nodesets/centos-510-x64.yml b/inifile/spec/acceptance/nodesets/centos-510-x64.yml new file mode 100644 index 000000000..12c9e7893 --- /dev/null +++ b/inifile/spec/acceptance/nodesets/centos-510-x64.yml @@ -0,0 +1,10 @@ +HOSTS: + centos-510-x64: + roles: + - master + platform: el-5-x86_64 + box : centos-510-x64-virtualbox-nocm + box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-510-x64-virtualbox-nocm.box + hypervisor : vagrant +CONFIG: + type: git diff --git a/inifile/spec/acceptance/nodesets/centos-59-x64.yml b/inifile/spec/acceptance/nodesets/centos-59-x64.yml new file mode 100644 index 000000000..2ad90b86a --- /dev/null +++ b/inifile/spec/acceptance/nodesets/centos-59-x64.yml @@ -0,0 +1,10 @@ +HOSTS: + centos-59-x64: + roles: + - master + platform: el-5-x86_64 + box : centos-59-x64-vbox4210-nocm + box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-59-x64-vbox4210-nocm.box + hypervisor : vagrant +CONFIG: + type: git diff --git a/inifile/spec/acceptance/nodesets/centos-64-x64-pe.yml b/inifile/spec/acceptance/nodesets/centos-64-x64-pe.yml new file mode 100644 index 000000000..7d9242f1b --- /dev/null +++ b/inifile/spec/acceptance/nodesets/centos-64-x64-pe.yml @@ -0,0 +1,12 @@ +HOSTS: + centos-64-x64: + roles: + - master + - database + - dashboard + platform: el-6-x86_64 + box : centos-64-x64-vbox4210-nocm + box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-64-x64-vbox4210-nocm.box + hypervisor : vagrant +CONFIG: + type: pe diff --git a/inifile/spec/acceptance/nodesets/centos-64-x64.yml b/inifile/spec/acceptance/nodesets/centos-64-x64.yml new file mode 100644 index 000000000..063983549 --- /dev/null +++ b/inifile/spec/acceptance/nodesets/centos-64-x64.yml @@ -0,0 +1,10 @@ +HOSTS: + centos-64-x64: + roles: + - master + platform: el-6-x86_64 + box : centos-64-x64-vbox4210-nocm + box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-64-x64-vbox4210-nocm.box + hypervisor : vagrant +CONFIG: + type: git diff --git a/inifile/spec/acceptance/nodesets/centos-65-x64.yml b/inifile/spec/acceptance/nodesets/centos-65-x64.yml new file mode 100644 index 000000000..4e2cb809e --- /dev/null +++ b/inifile/spec/acceptance/nodesets/centos-65-x64.yml @@ -0,0 +1,10 @@ +HOSTS: + centos-65-x64: + roles: + - master + platform: el-6-x86_64 + box : centos-65-x64-vbox436-nocm + box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-65-x64-virtualbox-nocm.box + hypervisor : vagrant +CONFIG: + type: foss diff --git a/inifile/spec/acceptance/nodesets/debian-607-x64.yml b/inifile/spec/acceptance/nodesets/debian-607-x64.yml new file mode 100644 index 000000000..4c8be42d0 --- /dev/null +++ b/inifile/spec/acceptance/nodesets/debian-607-x64.yml @@ -0,0 +1,10 @@ +HOSTS: + debian-607-x64: + roles: + - master + platform: debian-6-amd64 + box : debian-607-x64-vbox4210-nocm + box_url : http://puppet-vagrant-boxes.puppetlabs.com/debian-607-x64-vbox4210-nocm.box + hypervisor : vagrant +CONFIG: + type: git diff --git a/inifile/spec/acceptance/nodesets/debian-73-x64.yml b/inifile/spec/acceptance/nodesets/debian-73-x64.yml new file mode 100644 index 000000000..3e31a8276 --- /dev/null +++ b/inifile/spec/acceptance/nodesets/debian-73-x64.yml @@ -0,0 +1,10 @@ +HOSTS: + debian-73-x64: + roles: + - master + platform: debian-7-amd64 + box : debian-73-x64-virtualbox-nocm + box_url : http://puppet-vagrant-boxes.puppetlabs.com/debian-73-x64-virtualbox-nocm.box + hypervisor : vagrant +CONFIG: + type: git diff --git a/inifile/spec/acceptance/nodesets/default.yml b/inifile/spec/acceptance/nodesets/default.yml new file mode 100644 index 000000000..063983549 --- /dev/null +++ b/inifile/spec/acceptance/nodesets/default.yml @@ -0,0 +1,10 @@ +HOSTS: + centos-64-x64: + roles: + - master + platform: el-6-x86_64 + box : centos-64-x64-vbox4210-nocm + box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-64-x64-vbox4210-nocm.box + hypervisor : vagrant +CONFIG: + type: git diff --git a/inifile/spec/acceptance/nodesets/fedora-18-x64.yml b/inifile/spec/acceptance/nodesets/fedora-18-x64.yml new file mode 100644 index 000000000..624b53716 --- /dev/null +++ b/inifile/spec/acceptance/nodesets/fedora-18-x64.yml @@ -0,0 +1,10 @@ +HOSTS: + fedora-18-x64: + roles: + - master + platform: fedora-18-x86_64 + box : fedora-18-x64-vbox4210-nocm + box_url : http://puppet-vagrant-boxes.puppetlabs.com/fedora-18-x64-vbox4210-nocm.box + hypervisor : vagrant +CONFIG: + type: git diff --git a/inifile/spec/acceptance/nodesets/sles-11sp1-x64.yml b/inifile/spec/acceptance/nodesets/sles-11sp1-x64.yml new file mode 100644 index 000000000..554c37a50 --- /dev/null +++ b/inifile/spec/acceptance/nodesets/sles-11sp1-x64.yml @@ -0,0 +1,10 @@ +HOSTS: + sles-11sp1-x64: + roles: + - master + platform: sles-11-x86_64 + box : sles-11sp1-x64-vbox4210-nocm + box_url : http://puppet-vagrant-boxes.puppetlabs.com/sles-11sp1-x64-vbox4210-nocm.box + hypervisor : vagrant +CONFIG: + type: git diff --git a/inifile/spec/acceptance/nodesets/ubuntu-server-10044-x64.yml b/inifile/spec/acceptance/nodesets/ubuntu-server-10044-x64.yml new file mode 100644 index 000000000..5ca1514e4 --- /dev/null +++ b/inifile/spec/acceptance/nodesets/ubuntu-server-10044-x64.yml @@ -0,0 +1,10 @@ +HOSTS: + ubuntu-server-10044-x64: + roles: + - master + platform: ubuntu-10.04-amd64 + box : ubuntu-server-10044-x64-vbox4210-nocm + box_url : http://puppet-vagrant-boxes.puppetlabs.com/ubuntu-server-10044-x64-vbox4210-nocm.box + hypervisor : vagrant +CONFIG: + type: foss diff --git a/inifile/spec/acceptance/nodesets/ubuntu-server-12042-x64.yml b/inifile/spec/acceptance/nodesets/ubuntu-server-12042-x64.yml new file mode 100644 index 000000000..d065b304f --- /dev/null +++ b/inifile/spec/acceptance/nodesets/ubuntu-server-12042-x64.yml @@ -0,0 +1,10 @@ +HOSTS: + ubuntu-server-12042-x64: + roles: + - master + platform: ubuntu-12.04-amd64 + box : ubuntu-server-12042-x64-vbox4210-nocm + box_url : http://puppet-vagrant-boxes.puppetlabs.com/ubuntu-server-12042-x64-vbox4210-nocm.box + hypervisor : vagrant +CONFIG: + type: foss diff --git a/inifile/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml b/inifile/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml new file mode 100644 index 000000000..cba1cd04c --- /dev/null +++ b/inifile/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml @@ -0,0 +1,11 @@ +HOSTS: + ubuntu-server-1404-x64: + roles: + - master + platform: ubuntu-14.04-amd64 + box : puppetlabs/ubuntu-14.04-64-nocm + box_url : https://vagrantcloud.com/puppetlabs/ubuntu-14.04-64-nocm + hypervisor : vagrant +CONFIG: + log_level : debug + type: git diff --git a/inifile/spec/acceptance/nodesets/windows-2003-i386.yml b/inifile/spec/acceptance/nodesets/windows-2003-i386.yml new file mode 100644 index 000000000..eb571eea1 --- /dev/null +++ b/inifile/spec/acceptance/nodesets/windows-2003-i386.yml @@ -0,0 +1,24 @@ +HOSTS: + ubuntu1204: + roles: + - master + - database + - dashboard + platform: ubuntu-12.04-amd64 + template: ubuntu-1204-x86_64 + hypervisor: vcloud + win2003_i386: + roles: + - agent + - default + platform: windows-2003-i386 + template: win-2003-i386 + hypervisor: vcloud +CONFIG: + nfs_server: none + consoleport: 443 + datastore: instance0 + folder: Delivery/Quality Assurance/Enterprise/Dynamic + resourcepool: delivery/Quality Assurance/Enterprise/Dynamic + pooling_api: http://vcloud.delivery.puppetlabs.net/ + pe_dir: http://neptune.puppetlabs.lan/3.2/ci-ready/ diff --git a/inifile/spec/acceptance/nodesets/windows-2003r2-x86_64.yml b/inifile/spec/acceptance/nodesets/windows-2003r2-x86_64.yml new file mode 100644 index 000000000..e8659a5f8 --- /dev/null +++ b/inifile/spec/acceptance/nodesets/windows-2003r2-x86_64.yml @@ -0,0 +1,24 @@ +HOSTS: + ubuntu1204: + roles: + - master + - database + - dashboard + platform: ubuntu-12.04-amd64 + template: ubuntu-1204-x86_64 + hypervisor: vcloud + win2003r2_x86_64: + roles: + - agent + - default + platform: windows-2003r2-x86_64 + template: win-2003r2-x86_64 + hypervisor: vcloud +CONFIG: + nfs_server: none + consoleport: 443 + datastore: instance0 + folder: Delivery/Quality Assurance/Enterprise/Dynamic + resourcepool: delivery/Quality Assurance/Enterprise/Dynamic + pooling_api: http://vcloud.delivery.puppetlabs.net/ + pe_dir: http://neptune.puppetlabs.lan/3.3/ci-ready/ diff --git a/inifile/spec/acceptance/nodesets/windows-2008-x86_64.yml b/inifile/spec/acceptance/nodesets/windows-2008-x86_64.yml new file mode 100644 index 000000000..a5ebc4d2c --- /dev/null +++ b/inifile/spec/acceptance/nodesets/windows-2008-x86_64.yml @@ -0,0 +1,24 @@ +HOSTS: + ubuntu1204: + roles: + - master + - database + - dashboard + platform: ubuntu-12.04-amd64 + template: ubuntu-1204-x86_64 + hypervisor: vcloud + win2008_x86_64: + roles: + - agent + - default + platform: windows-2008-x86_64 + template: win-2008-x86_64 + hypervisor: vcloud +CONFIG: + nfs_server: none + consoleport: 443 + datastore: instance0 + folder: Delivery/Quality Assurance/Enterprise/Dynamic + resourcepool: delivery/Quality Assurance/Enterprise/Dynamic + pooling_api: http://vcloud.delivery.puppetlabs.net/ + pe_dir: http://neptune.puppetlabs.lan/3.3/ci-ready/ diff --git a/inifile/spec/acceptance/nodesets/windows-2008r2-x86_64.yml b/inifile/spec/acceptance/nodesets/windows-2008r2-x86_64.yml new file mode 100644 index 000000000..d2ddba3e4 --- /dev/null +++ b/inifile/spec/acceptance/nodesets/windows-2008r2-x86_64.yml @@ -0,0 +1,24 @@ +HOSTS: + ubuntu1204: + roles: + - master + - database + - dashboard + platform: ubuntu-12.04-amd64 + template: ubuntu-1204-x86_64 + hypervisor: vcloud + win2008r2: + roles: + - agent + - default + platform: windows-2008r2-x86_64 + template: win-2008r2-x86_64 + hypervisor: vcloud +CONFIG: + nfs_server: none + consoleport: 443 + datastore: instance0 + folder: Delivery/Quality Assurance/Enterprise/Dynamic + resourcepool: delivery/Quality Assurance/Enterprise/Dynamic + pooling_api: http://vcloud.delivery.puppetlabs.net/ + pe_dir: http://neptune.puppetlabs.lan/3.3/ci-ready/ diff --git a/inifile/spec/acceptance/nodesets/windows-2012-x86_64.yml b/inifile/spec/acceptance/nodesets/windows-2012-x86_64.yml new file mode 100644 index 000000000..deea3761b --- /dev/null +++ b/inifile/spec/acceptance/nodesets/windows-2012-x86_64.yml @@ -0,0 +1,24 @@ +HOSTS: + ubuntu1204: + roles: + - master + - database + - dashboard + platform: ubuntu-12.04-amd64 + template: ubuntu-1204-x86_64 + hypervisor: vcloud + win2012: + roles: + - agent + - default + platform: windows-2012-x86_64 + template: win-2012-x86_64 + hypervisor: vcloud +CONFIG: + nfs_server: none + consoleport: 443 + datastore: instance0 + folder: Delivery/Quality Assurance/Enterprise/Dynamic + resourcepool: delivery/Quality Assurance/Enterprise/Dynamic + pooling_api: http://vcloud.delivery.puppetlabs.net/ + pe_dir: http://neptune.puppetlabs.lan/3.3/ci-ready/ diff --git a/inifile/spec/acceptance/nodesets/windows-2012r2-x86_64.yml b/inifile/spec/acceptance/nodesets/windows-2012r2-x86_64.yml new file mode 100644 index 000000000..8f9149a3e --- /dev/null +++ b/inifile/spec/acceptance/nodesets/windows-2012r2-x86_64.yml @@ -0,0 +1,24 @@ +HOSTS: + ubuntu1204: + roles: + - master + - database + - dashboard + platform: ubuntu-12.04-amd64 + template: ubuntu-1204-x86_64 + hypervisor: vcloud + win2012r2: + roles: + - agent + - default + platform: windows-2012r2-x86_64 + template: win-2012r2-x86_64 + hypervisor: vcloud +CONFIG: + nfs_server: none + consoleport: 443 + datastore: instance0 + folder: Delivery/Quality Assurance/Enterprise/Dynamic + resourcepool: delivery/Quality Assurance/Enterprise/Dynamic + pooling_api: http://vcloud.delivery.puppetlabs.net/ + pe_dir: http://neptune.puppetlabs.lan/3.3/ci-ready/ diff --git a/inifile/spec/spec.opts b/inifile/spec/spec.opts new file mode 100644 index 000000000..91cd6427e --- /dev/null +++ b/inifile/spec/spec.opts @@ -0,0 +1,6 @@ +--format +s +--colour +--loadby +mtime +--backtrace diff --git a/inifile/spec/spec_helper.rb b/inifile/spec/spec_helper.rb index c2d12b5ec..7607c3312 100644 --- a/inifile/spec/spec_helper.rb +++ b/inifile/spec/spec_helper.rb @@ -1,11 +1,3 @@ -gem 'rspec', '>=2.0.0' -require 'rspec/expectations' - - -require 'puppetlabs_spec_helper/puppetlabs_spec_helper' - -require 'puppetlabs_spec_helper/puppetlabs_spec/files' - require 'puppetlabs_spec_helper/module_spec_helper' RSpec.configure do |config| diff --git a/inifile/spec/spec_helper_acceptance.rb b/inifile/spec/spec_helper_acceptance.rb new file mode 100644 index 000000000..bfa758429 --- /dev/null +++ b/inifile/spec/spec_helper_acceptance.rb @@ -0,0 +1,42 @@ +require 'beaker-rspec/spec_helper' +require 'beaker-rspec/helpers/serverspec' + +unless ENV['RS_PROVISION'] == 'no' + # This will install the latest available package on el and deb based + # systems fail on windows and osx, and install via gem on other *nixes + foss_opts = { :default_action => 'gem_install' } + + if default.is_pe?; then install_pe; else install_puppet( foss_opts ); end + + hosts.each do |host| + if host['platform'] =~ /debian/ + on host, 'echo \'export PATH=/var/lib/gems/1.8/bin/:${PATH}\' >> ~/.bashrc' + on host, "mkdir -p #{host['distmoduledir']}" + end + end +end + +RSpec.configure do |c| + # Project root + proj_root = File.expand_path(File.join(File.dirname(__FILE__), '..')) + + # Readable test descriptions + c.formatter = :documentation + + # Configure all nodes in nodeset + c.before :suite do + # Install module and dependencies + hosts.each do |host| + if host['platform'] !~ /windows/i + copy_root_module_to(host, :source => proj_root, :module_name => 'inifile') + end + end + hosts.each do |host| + if host['platform'] =~ /windows/i + on host, puppet('plugin download') + end + end + end + + c.treat_symbols_as_metadata_keys_with_true_values = true +end diff --git a/inifile/spec/unit/puppet/provider/ini_setting/ruby_spec.rb b/inifile/spec/unit/puppet/provider/ini_setting/ruby_spec.rb index 550dd72cd..1ab84b974 100644 --- a/inifile/spec/unit/puppet/provider/ini_setting/ruby_spec.rb +++ b/inifile/spec/unit/puppet/provider/ini_setting/ruby_spec.rb @@ -144,7 +144,7 @@ def self.file_path resource = Puppet::Type::Ini_setting.new(common_params.merge( :setting => 'yahoo', :value => 'yippee')) provider = described_class.new(resource) - provider.exists?.should be_nil + provider.exists?.should be false provider.create validate_file(<<-EOS # This is a comment @@ -172,7 +172,7 @@ def self.file_path resource = Puppet::Type::Ini_setting.new(common_params.merge( :section => 'section:sub', :setting => 'yahoo', :value => 'yippee')) provider = described_class.new(resource) - provider.exists?.should be_nil + provider.exists?.should be false provider.create validate_file(<<-EOS # This is a comment @@ -200,7 +200,7 @@ def self.file_path resource = Puppet::Type::Ini_setting.new(common_params.merge( :setting => 'baz', :value => 'bazvalue2')) provider = described_class.new(resource) - provider.exists?.should == 'bazvalue' + provider.exists?.should be true provider.value=('bazvalue2') validate_file(<<-EOS # This is a comment @@ -227,7 +227,7 @@ def self.file_path resource = Puppet::Type::Ini_setting.new(common_params.merge( :section => 'section:sub', :setting => 'subby', :value => 'foo')) provider = described_class.new(resource) - provider.exists?.should == 'bar' + provider.exists?.should be true provider.value.should == 'bar' provider.value=('foo') validate_file(<<-EOS @@ -255,7 +255,7 @@ def self.file_path resource = Puppet::Type::Ini_setting.new(common_params.merge( :setting => 'url', :value => 'http://192.168.0.1:8080')) provider = described_class.new(resource) - provider.exists?.should == 'http://192.168.1.1:8080' + provider.exists?.should be true provider.value.should == 'http://192.168.1.1:8080' provider.value=('http://192.168.0.1:8080') @@ -284,14 +284,14 @@ def self.file_path resource = Puppet::Type::Ini_setting.new(common_params.merge( :setting => 'baz', :value => 'bazvalue')) provider = described_class.new(resource) - provider.exists?.should == 'bazvalue' + provider.exists?.should be true end it "should add a new section if the section does not exist" do resource = Puppet::Type::Ini_setting.new(common_params.merge( :section => "section3", :setting => 'huzzah', :value => 'shazaam')) provider = described_class.new(resource) - provider.exists?.should be_nil + provider.exists?.should be false provider.create validate_file(<<-EOS # This is a comment @@ -321,7 +321,7 @@ def self.file_path resource = Puppet::Type::Ini_setting.new(common_params.merge( :section => "section:subsection", :setting => 'huzzah', :value => 'shazaam')) provider = described_class.new(resource) - provider.exists?.should be_nil + provider.exists?.should be false provider.create validate_file(<<-EOS # This is a comment @@ -351,7 +351,7 @@ def self.file_path resource = Puppet::Type::Ini_setting.new(common_params.merge( :section => "section1", :setting => 'setting1', :value => 'hellowworld', :path => emptyfile)) provider = described_class.new(resource) - provider.exists?.should be_nil + provider.exists?.should be false provider.create validate_file(" [section1] @@ -363,7 +363,7 @@ def self.file_path resource = Puppet::Type::Ini_setting.new(common_params.merge( :section => "section:subsection", :setting => 'setting1', :value => 'hellowworld', :path => emptyfile)) provider = described_class.new(resource) - provider.exists?.should be_nil + provider.exists?.should be false provider.create validate_file(" [section:subsection] @@ -375,7 +375,7 @@ def self.file_path resource = Puppet::Type::Ini_setting.new(common_params.merge( :section => "section1", :setting => 'master', :value => true)) provider = described_class.new(resource) - provider.exists?.should == 'true' + provider.exists?.should be true provider.value.should == 'true' end @@ -397,7 +397,7 @@ def self.file_path resource = Puppet::Type::Ini_setting.new(common_params.merge( :section => '', :setting => 'bar', :value => 'yippee')) provider = described_class.new(resource) - provider.exists?.should be_nil + provider.exists?.should be false provider.create validate_file(<<-EOS # This is a comment @@ -414,7 +414,7 @@ def self.file_path resource = Puppet::Type::Ini_setting.new(common_params.merge( :section => '', :setting => 'foo', :value => 'yippee')) provider = described_class.new(resource) - provider.exists?.should == 'blah' + provider.exists?.should be true provider.value.should == 'blah' provider.value=('yippee') validate_file(<<-EOS @@ -431,7 +431,7 @@ def self.file_path resource = Puppet::Type::Ini_setting.new(common_params.merge( :section => '', :setting => 'foo', :value => 'blah')) provider = described_class.new(resource) - provider.exists?.should == 'blah' + provider.exists?.should be true end end @@ -447,7 +447,7 @@ def self.file_path resource = Puppet::Type::Ini_setting.new(common_params.merge( :section => '', :setting => 'foo', :value => 'yippee')) provider = described_class.new(resource) - provider.exists?.should be_nil + provider.exists?.should be false provider.create validate_file(<<-EOS foo = yippee @@ -462,7 +462,7 @@ def self.file_path resource = Puppet::Type::Ini_setting.new(common_params.merge( :section => 'section2', :setting => 'foo', :value => 'yippee')) provider = described_class.new(resource) - provider.exists?.should == 'http://192.168.1.1:8080' + provider.exists?.should be true provider.value.should == 'http://192.168.1.1:8080' provider.value=('yippee') validate_file(<<-EOS @@ -476,7 +476,7 @@ def self.file_path resource = Puppet::Type::Ini_setting.new(common_params.merge( :section => 'section2', :setting => 'bar', :value => 'baz')) provider = described_class.new(resource) - provider.exists?.should be_nil + provider.exists?.should be false provider.create validate_file(<<-EOS [section2] @@ -522,7 +522,7 @@ def self.file_path :value => 'yippee', :key_val_separator => '=')) provider = described_class.new(resource) - provider.exists?.should == 'bar' + provider.exists?.should be true provider.value.should == 'bar' provider.value=('yippee') validate_file(<<-EOS @@ -539,7 +539,7 @@ def self.file_path :value => 'baz', :key_val_separator => '=')) provider = described_class.new(resource) - provider.exists?.should be_nil + provider.exists?.should be false provider.create validate_file(<<-EOS [section2] @@ -576,7 +576,7 @@ def self.file_path resource = Puppet::Type::Ini_setting.new(common_params.merge( :section => 'section1', :setting => 'foo', :ensure => 'absent')) provider = described_class.new(resource) - provider.exists?.should be_true + provider.exists?.should be true provider.destroy validate_file(<<-EOS [section1] @@ -601,7 +601,7 @@ def self.file_path resource = Puppet::Type::Ini_setting.new(common_params.merge( :section => 'section:sub', :setting => 'foo', :ensure => 'absent')) provider = described_class.new(resource) - provider.exists?.should be_nil + provider.exists?.should be false provider.destroy validate_file(<<-EOS [section1] @@ -652,7 +652,7 @@ def self.file_path resource = Puppet::Type::Ini_setting.new(common_params.merge( :section => 'section1', :setting => 'yahoo', :value => 'yippee')) provider = described_class.new(resource) - provider.exists?.should be_nil + provider.exists?.should be false provider.create validate_file(<<-EOS # This is a comment @@ -681,7 +681,7 @@ def self.file_path resource = Puppet::Type::Ini_setting.new( common_params.merge(:section => 'section1', :setting => 'bar', :value => 'barvalue2')) provider = described_class.new(resource) - provider.exists?.should be_true + provider.exists?.should be true provider.create validate_file(<<-EOS # This is a comment @@ -709,7 +709,7 @@ def self.file_path resource = Puppet::Type::Ini_setting.new(common_params.merge( :section => 'section2', :setting => 'yahoo', :value => 'yippee')) provider = described_class.new(resource) - provider.exists?.should be_nil + provider.exists?.should be false provider.create validate_file(<<-EOS # This is a comment @@ -738,7 +738,7 @@ def self.file_path resource = Puppet::Type::Ini_setting.new( common_params.merge(:section => 'section2', :setting => 'baz', :value => 'bazvalue2')) provider = described_class.new(resource) - provider.exists?.should be_true + provider.exists?.should be true provider.create validate_file(<<-EOS # This is a comment @@ -766,7 +766,7 @@ def self.file_path resource = Puppet::Type::Ini_setting.new( common_params.merge(:section => 'section:sub', :setting => 'yahoo', :value => 'yippee')) provider = described_class.new(resource) - provider.exists?.should be_nil + provider.exists?.should be false provider.create validate_file(<<-EOS # This is a comment @@ -795,7 +795,7 @@ def self.file_path resource = Puppet::Type::Ini_setting.new( common_params.merge(:section => 'section:sub', :setting => 'fleezy', :value => 'flam2')) provider = described_class.new(resource) - provider.exists?.should be_true + provider.exists?.should be true provider.create validate_file(<<-EOS # This is a comment @@ -842,7 +842,7 @@ def self.file_path resource = Puppet::Type::Ini_setting.new( common_params.merge(:section => 'section2', :setting => 'foo', :value => 'foo3')) provider = described_class.new(resource) - provider.exists?.should be_false + provider.exists?.should be false provider.create validate_file(<<-EOS [section1] @@ -864,7 +864,7 @@ def self.file_path resource = Puppet::Type::Ini_setting.new( common_params.merge(:section => 'section1', :setting => 'foo', :value => 'foo3')) provider = described_class.new(resource) - provider.exists?.should be_true + provider.exists?.should be true provider.create validate_file(<<-EOS [section1] @@ -885,7 +885,7 @@ def self.file_path resource = Puppet::Type::Ini_setting.new( common_params.merge(:section => 'section2', :setting => 'bar', :value => 'bar3')) provider = described_class.new(resource) - provider.exists?.should be_false + provider.exists?.should be false provider.create validate_file(<<-EOS [section1] @@ -907,7 +907,7 @@ def self.file_path resource = Puppet::Type::Ini_setting.new( common_params.merge(:section => 'section2', :setting => 'baz', :value => 'bazvalue')) provider = described_class.new(resource) - provider.exists?.should be_false + provider.exists?.should be false provider.create validate_file(<<-EOS [section1] @@ -938,7 +938,7 @@ def self.file_path common_params.merge(:section => 'section1', :setting => 'foo', :value => 'foovalue2') ) provider = described_class.new(resource) - provider.exists?.should be_false + provider.exists?.should be false provider.create validate_file(<<-EOS [section1] @@ -953,7 +953,7 @@ def self.file_path common_params.merge(:section => 'section1', :setting => 'bar', :value => 'barvalue2') ) provider = described_class.new(resource) - provider.exists?.should be_false + provider.exists?.should be false provider.create validate_file(<<-EOS [section1] @@ -965,6 +965,99 @@ def self.file_path end end + context "when sections have spaces and dashes" do + let(:orig_content) { + <<-EOS +# This is a comment +[section - one] +; This is also a comment +foo=foovalue + +bar = barvalue +master = true +[section - two] + +foo= foovalue2 +baz=bazvalue +url = http://192.168.1.1:8080 +[section:sub] +subby=bar + #another comment + ; yet another comment + EOS + } + + it "should add a missing setting to the correct section" do + resource = Puppet::Type::Ini_setting.new(common_params.merge( + :section => 'section - two', :setting => 'yahoo', :value => 'yippee')) + provider = described_class.new(resource) + provider.exists?.should be false + provider.create + validate_file(<<-EOS +# This is a comment +[section - one] +; This is also a comment +foo=foovalue + +bar = barvalue +master = true +[section - two] + +foo= foovalue2 +baz=bazvalue +url = http://192.168.1.1:8080 +yahoo = yippee +[section:sub] +subby=bar + #another comment + ; yet another comment + EOS + ) + end + + end + + end + + context "when sections have spaces and quotations" do + let(:orig_content) do + <<-EOS +[branch "master"] + remote = origin + merge = refs/heads/master + +[alias] +to-deploy = log --merges --grep='pull request' --format='%s (%cN)' origin/production..origin/master +[branch "production"] + remote = origin + merge = refs/heads/production + EOS + end + + it "should add a missing setting to the correct section" do + resource = Puppet::Type::Ini_setting.new(common_params.merge( + :section => 'alias', + :setting => 'foo', + :value => 'bar' + )) + provider = described_class.new(resource) + provider.exists?.should be false + provider.create + validate_file(<<-EOS +[branch "master"] + remote = origin + merge = refs/heads/master + +[alias] +to-deploy = log --merges --grep='pull request' --format='%s (%cN)' origin/production..origin/master +foo = bar +[branch "production"] + remote = origin + merge = refs/heads/production + EOS + ) + end + end end diff --git a/inifile/spec/unit/puppet/util/ini_file_spec.rb b/inifile/spec/unit/puppet/util/ini_file_spec.rb index 8ab18cf24..41b3cebc1 100644 --- a/inifile/spec/unit/puppet/util/ini_file_spec.rb +++ b/inifile/spec/unit/puppet/util/ini_file_spec.rb @@ -26,9 +26,12 @@ 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") } @@ -44,12 +47,19 @@ end it "should expose settings for sections" do - subject.get_value("section1", "foo").should == "foovalue" - subject.get_value("section1", "bar").should == "barvalue" - subject.get_value("section1", "baz").should == "" - subject.get_value("section2", "foo").should == "foovalue2" - subject.get_value("section2", "baz").should == "bazvalue" - subject.get_value("section2", "zot").should == "multi word value" + subject.get_settings("section1").should == { + "bar" => "barvalue", + "baz" => "", + "foo" => "foovalue" + } + + subject.get_settings("section2").should == { + "baz" => "bazvalue", + "foo" => "foovalue2", + "l" => "git log", + "xyzzy['thing1']['thing2']" => "xyzzyvalue", + "zot" => "multi word value" + } end end @@ -113,6 +123,7 @@ [section1] foo= #bar= +#xyzzy['thing1']['thing2']='xyzzyvalue' EOS template.split("\n") } @@ -127,6 +138,9 @@ subject.get_value("section1", "bar").should == nil subject.set_value("section1", "bar", "barvalue") subject.get_value("section1", "bar").should == "barvalue" + subject.get_value("section1", "xyzzy['thing1']['thing2']").should == nil + subject.set_value("section1", "xyzzy['thing1']['thing2']", "xyzzyvalue") + subject.get_value("section1", "xyzzy['thing1']['thing2']").should == "xyzzyvalue" end it "should properly add new empty values" do @@ -135,4 +149,117 @@ subject.get_value("section1", "baz").should == "bazvalue" end end + + context 'the file has quotation marks in its section names' do + let(:sample_content) do + template = <<-EOS +[branch "master"] + remote = origin + merge = refs/heads/master + +[alias] +to-deploy = log --merges --grep='pull request' --format='%s (%cN)' origin/production..origin/master +[branch "production"] + remote = origin + merge = refs/heads/production + EOS + template.split("\n") + end + + it 'should parse the sections' do + subject.section_names.should match_array ['', + 'branch "master"', + 'alias', + 'branch "production"' + ] + end + end + + context 'Samba INI file with dollars in section names' do + let(:sample_content) do + template = <<-EOS + [global] + workgroup = FELLOWSHIP + ; ... + idmap config * : backend = tdb + + [printers] + comment = All Printers + ; ... + browseable = No + + [print$] + comment = Printer Drivers + path = /var/lib/samba/printers + + [Shares] + path = /home/shares + read only = No + guest ok = Yes + EOS + template.split("\n") + end + + it "should parse the correct section_names" do + subject.section_names.should match_array [ + '', + 'global', + 'printers', + 'print$', + 'Shares' + ] + end + end + + context 'section names with forward slashes in them' do + let(:sample_content) do + template = <<-EOS +[monitor:///var/log/*.log] +disabled = test_value + EOS + template.split("\n") + end + + it "should parse the correct section_names" do + subject.section_names.should match_array [ + '', + 'monitor:///var/log/*.log' + ] + end + end + + context 'KDE Configuration with braces in setting names' do + let(:sample_content) do + template = <<-EOS + [khotkeys] +_k_friendly_name=khotkeys +{5465e8c7-d608-4493-a48f-b99d99fdb508}=Print,none,PrintScreen +{d03619b6-9b3c-48cc-9d9c-a2aadb485550}=Search,none,Search +EOS + template.split("\n") + end + + it "should expose settings for sections" do + subject.get_value("khotkeys", "{5465e8c7-d608-4493-a48f-b99d99fdb508}").should == "Print,none,PrintScreen" + subject.get_value("khotkeys", "{d03619b6-9b3c-48cc-9d9c-a2aadb485550}").should == "Search,none,Search" + end + end + + context 'Configuration with colons in setting names' do + let(:sample_content) do + template = <<-EOS + [Drive names] +A:=5.25" Floppy +B:=3.5" Floppy +C:=Winchester +EOS + template.split("\n") + end + + it "should expose settings for sections" do + subject.get_value("Drive names", "A:").should eq '5.25" Floppy' + subject.get_value("Drive names", "B:").should eq '3.5" Floppy' + subject.get_value("Drive names", "C:").should eq 'Winchester' + end + end end diff --git a/inifile/spec/unit/puppet/util/setting_value_spec.rb b/inifile/spec/unit/puppet/util/setting_value_spec.rb index 61483968a..8514724c3 100644 --- a/inifile/spec/unit/puppet/util/setting_value_spec.rb +++ b/inifile/spec/unit/puppet/util/setting_value_spec.rb @@ -66,4 +66,38 @@ @setting_value.get_subsetting_value("-Xmx").should == nil end end + + describe "quote_char parameter" do + QUOTE_CHAR = '"' + INIT_VALUE_UNQUOTED = '-Xmx192m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/pe-puppetdb/puppetdb-oom.hprof' + + it "should get quoted empty string if original value was empty" do + setting_value = Puppet::Util::SettingValue.new(nil, ' ', QUOTE_CHAR) + setting_value.get_value.should == QUOTE_CHAR * 2 + end + + it "should quote the setting when adding a value" do + setting_value = Puppet::Util::SettingValue.new(INIT_VALUE_UNQUOTED, ' ', QUOTE_CHAR) + setting_value.add_subsetting("-Xms", "256m") + + setting_value.get_subsetting_value("-Xms").should == "256m" + setting_value.get_value.should == QUOTE_CHAR + INIT_VALUE_UNQUOTED + ' -Xms256m' + QUOTE_CHAR + end + + it "should quote the setting when changing an existing value" do + setting_value = Puppet::Util::SettingValue.new(INIT_VALUE_UNQUOTED, ' ', QUOTE_CHAR) + setting_value.add_subsetting("-Xmx", "512m") + + setting_value.get_subsetting_value("-Xmx").should == "512m" + setting_value.get_value.should =~ /^#{Regexp.quote(QUOTE_CHAR)}.*#{Regexp.quote(QUOTE_CHAR)}$/ + end + + it "should quote the setting when removing an existing value" do + setting_value = Puppet::Util::SettingValue.new(INIT_VALUE_UNQUOTED, ' ', QUOTE_CHAR) + setting_value.remove_subsetting("-Xmx") + + setting_value.get_subsetting_value("-Xmx").should == nil + setting_value.get_value.should =~ /^#{Regexp.quote(QUOTE_CHAR)}.*#{Regexp.quote(QUOTE_CHAR)}$/ + end + end end